1 | /*
|
---|
2 | * Copyright 2002-2005 Jason Edmeades
|
---|
3 | * Copyright 2002-2005 Raphael Junqueira
|
---|
4 | * Copyright 2005 Oliver Stieber
|
---|
5 | * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers
|
---|
6 | * Copyright 2009-2011 Henri Verbeet for CodeWeavers
|
---|
7 | *
|
---|
8 | * This library is free software; you can redistribute it and/or
|
---|
9 | * modify it under the terms of the GNU Lesser General Public
|
---|
10 | * License as published by the Free Software Foundation; either
|
---|
11 | * version 2.1 of the License, or (at your option) any later version.
|
---|
12 | *
|
---|
13 | * This library is distributed in the hope that it will be useful,
|
---|
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
16 | * Lesser General Public License for more details.
|
---|
17 | *
|
---|
18 | * You should have received a copy of the GNU Lesser General Public
|
---|
19 | * License along with this library; if not, write to the Free Software
|
---|
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
---|
21 | */
|
---|
22 |
|
---|
23 | /*
|
---|
24 | * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
|
---|
25 | * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
|
---|
26 | * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
|
---|
27 | * a choice of LGPL license versions is made available with the language indicating
|
---|
28 | * that LGPLv2 or any later version may be used, or where a choice of which version
|
---|
29 | * of the LGPL is applied is otherwise unspecified.
|
---|
30 | */
|
---|
31 |
|
---|
32 | #include "config.h"
|
---|
33 | #include "wine/port.h"
|
---|
34 | #include "wined3d_private.h"
|
---|
35 |
|
---|
36 | #ifdef VBOX_WITH_WDDM
|
---|
37 | # include "../../common/VBoxVideoTools.h"
|
---|
38 | #endif
|
---|
39 |
|
---|
40 | WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
|
---|
41 |
|
---|
42 | static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_texture_ops *texture_ops,
|
---|
43 | UINT layer_count, UINT level_count, const struct wined3d_resource_desc *desc, struct wined3d_device *device,
|
---|
44 | void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops
|
---|
45 | #ifdef VBOX_WITH_WDDM
|
---|
46 | , HANDLE *shared_handle
|
---|
47 | , void **pavClientMem
|
---|
48 | #endif
|
---|
49 | )
|
---|
50 | {
|
---|
51 | const struct wined3d_format *format = wined3d_get_format(&device->adapter->gl_info, desc->format);
|
---|
52 | HRESULT hr;
|
---|
53 |
|
---|
54 | TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, "
|
---|
55 | "multisample_type %#x, multisample_quality %#x, usage %s, pool %s, width %u, height %u, depth %u, "
|
---|
56 | "device %p, parent %p, parent_ops %p, resource_ops %p.\n",
|
---|
57 | texture, texture_ops, layer_count, level_count, debug_d3dresourcetype(desc->resource_type),
|
---|
58 | debug_d3dformat(desc->format), desc->multisample_type, desc->multisample_quality,
|
---|
59 | debug_d3dusage(desc->usage), debug_d3dpool(desc->pool), desc->width, desc->height, desc->depth,
|
---|
60 | device, parent, parent_ops, resource_ops);
|
---|
61 |
|
---|
62 | #ifdef VBOX_WITH_WDDM
|
---|
63 | if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
|
---|
64 | desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool,
|
---|
65 | desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops,
|
---|
66 | shared_handle, pavClientMem ? pavClientMem[0] : NULL)))
|
---|
67 | #else
|
---|
68 | if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
|
---|
69 | desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool,
|
---|
70 | desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops)))
|
---|
71 | #endif
|
---|
72 | {
|
---|
73 | WARN("Failed to initialize resource, returning %#x\n", hr);
|
---|
74 | return hr;
|
---|
75 | }
|
---|
76 |
|
---|
77 | texture->texture_ops = texture_ops;
|
---|
78 | texture->sub_resources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
---|
79 | level_count * layer_count * sizeof(*texture->sub_resources));
|
---|
80 | if (!texture->sub_resources)
|
---|
81 | {
|
---|
82 | ERR("Failed to allocate sub-resource array.\n");
|
---|
83 | resource_cleanup(&texture->resource);
|
---|
84 | return E_OUTOFMEMORY;
|
---|
85 | }
|
---|
86 |
|
---|
87 | texture->layer_count = layer_count;
|
---|
88 | texture->level_count = level_count;
|
---|
89 | texture->filter_type = (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3D_TEXF_LINEAR : WINED3D_TEXF_NONE;
|
---|
90 | texture->lod = 0;
|
---|
91 | texture->texture_rgb.dirty = TRUE;
|
---|
92 | texture->texture_srgb.dirty = TRUE;
|
---|
93 | texture->flags = WINED3D_TEXTURE_POW2_MAT_IDENT;
|
---|
94 |
|
---|
95 | if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
|
---|
96 | {
|
---|
97 | texture->min_mip_lookup = minMipLookup;
|
---|
98 | texture->mag_lookup = magLookup;
|
---|
99 | }
|
---|
100 | else
|
---|
101 | {
|
---|
102 | texture->min_mip_lookup = minMipLookup_noFilter;
|
---|
103 | texture->mag_lookup = magLookup_noFilter;
|
---|
104 | }
|
---|
105 |
|
---|
106 | return WINED3D_OK;
|
---|
107 | }
|
---|
108 |
|
---|
109 | /* A GL context is provided by the caller */
|
---|
110 | static void gltexture_delete(const struct wined3d_gl_info *gl_info, struct gl_texture *tex)
|
---|
111 | {
|
---|
112 | #ifdef VBOX_WITH_WDDM
|
---|
113 | texture_gl_delete(tex->name);
|
---|
114 | #else
|
---|
115 | gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex->name);
|
---|
116 | #endif
|
---|
117 | tex->name = 0;
|
---|
118 | }
|
---|
119 |
|
---|
120 | static void wined3d_texture_unload(struct wined3d_texture *texture)
|
---|
121 | {
|
---|
122 | struct wined3d_device *device = texture->resource.device;
|
---|
123 | struct wined3d_context *context = NULL;
|
---|
124 |
|
---|
125 | if (texture->texture_rgb.name || texture->texture_srgb.name)
|
---|
126 | {
|
---|
127 | context = context_acquire(device, NULL);
|
---|
128 | }
|
---|
129 |
|
---|
130 | if (texture->texture_rgb.name)
|
---|
131 | gltexture_delete(context->gl_info, &texture->texture_rgb);
|
---|
132 |
|
---|
133 | if (texture->texture_srgb.name)
|
---|
134 | gltexture_delete(context->gl_info, &texture->texture_srgb);
|
---|
135 |
|
---|
136 | if (context) context_release(context);
|
---|
137 |
|
---|
138 | wined3d_texture_set_dirty(texture, TRUE);
|
---|
139 |
|
---|
140 | resource_unload(&texture->resource);
|
---|
141 | }
|
---|
142 |
|
---|
143 | static void wined3d_texture_cleanup(struct wined3d_texture *texture)
|
---|
144 | {
|
---|
145 | UINT sub_count = texture->level_count * texture->layer_count;
|
---|
146 | UINT i;
|
---|
147 |
|
---|
148 | TRACE("texture %p.\n", texture);
|
---|
149 |
|
---|
150 | #ifdef VBOX_WITH_WINE_FIX_TEXCLEAR
|
---|
151 | /* make texture unload first, because otherwise we may fail on context_acquire done for texture cleanup
|
---|
152 | * because the swapchain's surfaces might be destroyed and we may fail to select any render target in context_acquire */
|
---|
153 | wined3d_texture_unload(texture);
|
---|
154 | #endif
|
---|
155 |
|
---|
156 | for (i = 0; i < sub_count; ++i)
|
---|
157 | {
|
---|
158 | struct wined3d_resource *sub_resource = texture->sub_resources[i];
|
---|
159 |
|
---|
160 | if (sub_resource)
|
---|
161 | texture->texture_ops->texture_sub_resource_cleanup(sub_resource);
|
---|
162 | }
|
---|
163 |
|
---|
164 | #ifndef VBOX_WITH_WINE_FIX_TEXCLEAR
|
---|
165 | wined3d_texture_unload(texture);
|
---|
166 | #endif
|
---|
167 | HeapFree(GetProcessHeap(), 0, texture->sub_resources);
|
---|
168 | resource_cleanup(&texture->resource);
|
---|
169 | }
|
---|
170 |
|
---|
171 | void wined3d_texture_set_dirty(struct wined3d_texture *texture, BOOL dirty)
|
---|
172 | {
|
---|
173 | texture->texture_rgb.dirty = dirty;
|
---|
174 | texture->texture_srgb.dirty = dirty;
|
---|
175 | }
|
---|
176 |
|
---|
177 | /* Context activation is done by the caller. */
|
---|
178 | static HRESULT wined3d_texture_bind(struct wined3d_texture *texture,
|
---|
179 | struct wined3d_context *context, BOOL srgb, BOOL *set_surface_desc)
|
---|
180 | {
|
---|
181 | const struct wined3d_gl_info *gl_info = context->gl_info;
|
---|
182 | struct gl_texture *gl_tex;
|
---|
183 | BOOL new_texture = FALSE;
|
---|
184 | HRESULT hr = WINED3D_OK;
|
---|
185 | GLenum target;
|
---|
186 |
|
---|
187 | TRACE("texture %p, context %p, srgb %#x, set_surface_desc %p.\n", texture, context, srgb, set_surface_desc);
|
---|
188 |
|
---|
189 | /* sRGB mode cache for preload() calls outside drawprim. */
|
---|
190 | if (srgb)
|
---|
191 | texture->flags |= WINED3D_TEXTURE_IS_SRGB;
|
---|
192 | else
|
---|
193 | texture->flags &= ~WINED3D_TEXTURE_IS_SRGB;
|
---|
194 |
|
---|
195 | gl_tex = wined3d_texture_get_gl_texture(texture, context->gl_info, srgb);
|
---|
196 | target = texture->target;
|
---|
197 |
|
---|
198 | /* Generate a texture name if we don't already have one. */
|
---|
199 | if (!gl_tex->name)
|
---|
200 | {
|
---|
201 | #ifdef VBOX_WITH_WDDM
|
---|
202 | if (VBOXSHRC_IS_SHARED_OPENED(texture))
|
---|
203 | {
|
---|
204 | ERR("should not be here!");
|
---|
205 | gl_tex->name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
|
---|
206 | pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, gl_tex->name);
|
---|
207 | TRACE("Assigned shared texture %d\n", gl_tex->name);
|
---|
208 | }
|
---|
209 | else
|
---|
210 | #endif
|
---|
211 | {
|
---|
212 | #ifdef VBOX_WITH_WDDM
|
---|
213 | new_texture = TRUE;
|
---|
214 | #endif
|
---|
215 | *set_surface_desc = TRUE;
|
---|
216 | gl_info->gl_ops.gl.p_glGenTextures(1, &gl_tex->name);
|
---|
217 | checkGLcall("glGenTextures");
|
---|
218 | TRACE("Generated texture %d.\n", gl_tex->name);
|
---|
219 | #ifdef VBOX_WITH_WDDM
|
---|
220 | if (VBOXSHRC_IS_SHARED(texture))
|
---|
221 | {
|
---|
222 | VBOXSHRC_SET_SHAREHANDLE(texture, gl_tex->name);
|
---|
223 | }
|
---|
224 | #endif
|
---|
225 | }
|
---|
226 | #ifndef VBOX
|
---|
227 | if (texture->resource.pool == WINED3D_POOL_DEFAULT)
|
---|
228 | {
|
---|
229 | /* Tell OpenGL to try and keep this texture in video ram (well mostly). */
|
---|
230 | GLclampf tmp = 0.9f;
|
---|
231 | gl_info->gl_ops.gl.p_glPrioritizeTextures(1, &gl_tex->name, &tmp);
|
---|
232 | }
|
---|
233 | #else
|
---|
234 | /* chromium code on host fails to resolve texture name to texture obj,
|
---|
235 | * most likely because the texture does not get created until it is bound
|
---|
236 | * @todo: investigate */
|
---|
237 | #endif
|
---|
238 | /* Initialise the state of the texture object to the OpenGL defaults,
|
---|
239 | * not the D3D defaults. */
|
---|
240 | gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
|
---|
241 | gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
|
---|
242 | gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
|
---|
243 | gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
|
---|
244 | gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
|
---|
245 | gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
|
---|
246 | gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
|
---|
247 | gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
|
---|
248 | gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
|
---|
249 | if (context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
|
---|
250 | gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
|
---|
251 | else
|
---|
252 | gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = srgb;
|
---|
253 | gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
|
---|
254 | wined3d_texture_set_dirty(texture, TRUE);
|
---|
255 | #ifndef VBOX_WITH_WDDM
|
---|
256 | new_texture = TRUE;
|
---|
257 | #endif
|
---|
258 |
|
---|
259 | #ifdef VBOX_WITH_WDDM
|
---|
260 | if (new_texture
|
---|
261 | && texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)
|
---|
262 | #else
|
---|
263 | if (texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)
|
---|
264 | #endif
|
---|
265 | {
|
---|
266 | /* This means double binding the texture at creation, but keeps
|
---|
267 | * the code simpler all in all, and the run-time path free from
|
---|
268 | * additional checks. */
|
---|
269 | context_bind_texture(context, target, gl_tex->name);
|
---|
270 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
---|
271 | checkGLcall("glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)");
|
---|
272 | }
|
---|
273 | }
|
---|
274 | else
|
---|
275 | {
|
---|
276 | *set_surface_desc = FALSE;
|
---|
277 | }
|
---|
278 |
|
---|
279 | if (gl_tex->name)
|
---|
280 | {
|
---|
281 | context_bind_texture(context, target, gl_tex->name);
|
---|
282 | if (new_texture)
|
---|
283 | {
|
---|
284 | /* For a new texture we have to set the texture levels after
|
---|
285 | * binding the texture. Beware that texture rectangles do not
|
---|
286 | * support mipmapping, but set the maxmiplevel if we're relying
|
---|
287 | * on the partial GL_ARB_texture_non_power_of_two emulation with
|
---|
288 | * texture rectangles. (I.e., do not care about cond_np2 here,
|
---|
289 | * just look for GL_TEXTURE_RECTANGLE_ARB.) */
|
---|
290 | if (target != GL_TEXTURE_RECTANGLE_ARB)
|
---|
291 | {
|
---|
292 | TRACE("Setting GL_TEXTURE_MAX_LEVEL to %u.\n", texture->level_count - 1);
|
---|
293 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count - 1);
|
---|
294 | checkGLcall("glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count)");
|
---|
295 | }
|
---|
296 | if (target == GL_TEXTURE_CUBE_MAP_ARB)
|
---|
297 | {
|
---|
298 | /* Cubemaps are always set to clamp, regardless of the sampler state. */
|
---|
299 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
300 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
301 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
---|
302 | }
|
---|
303 | }
|
---|
304 | }
|
---|
305 | else
|
---|
306 | {
|
---|
307 | ERR("This texture doesn't have an OpenGL texture assigned to it.\n");
|
---|
308 | hr = WINED3DERR_INVALIDCALL;
|
---|
309 | }
|
---|
310 |
|
---|
311 | return hr;
|
---|
312 | }
|
---|
313 |
|
---|
314 | /* Context activation is done by the caller. */
|
---|
315 | static void apply_wrap(const struct wined3d_gl_info *gl_info, GLenum target,
|
---|
316 | enum wined3d_texture_address d3d_wrap, GLenum param, BOOL cond_np2)
|
---|
317 | {
|
---|
318 | GLint gl_wrap;
|
---|
319 |
|
---|
320 | if (d3d_wrap < WINED3D_TADDRESS_WRAP || d3d_wrap > WINED3D_TADDRESS_MIRROR_ONCE)
|
---|
321 | {
|
---|
322 | FIXME("Unrecognized or unsupported texture address mode %#x.\n", d3d_wrap);
|
---|
323 | return;
|
---|
324 | }
|
---|
325 |
|
---|
326 | /* Cubemaps are always set to clamp, regardless of the sampler state. */
|
---|
327 | if (target == GL_TEXTURE_CUBE_MAP_ARB
|
---|
328 | || (cond_np2 && d3d_wrap == WINED3D_TADDRESS_WRAP))
|
---|
329 | gl_wrap = GL_CLAMP_TO_EDGE;
|
---|
330 | else
|
---|
331 | gl_wrap = gl_info->wrap_lookup[d3d_wrap - WINED3D_TADDRESS_WRAP];
|
---|
332 |
|
---|
333 | TRACE("Setting param %#x to %#x for target %#x.\n", param, gl_wrap, target);
|
---|
334 | gl_info->gl_ops.gl.p_glTexParameteri(target, param, gl_wrap);
|
---|
335 | checkGLcall("glTexParameteri(target, param, gl_wrap)");
|
---|
336 | }
|
---|
337 |
|
---|
338 | /* Context activation is done by the caller (state handler). */
|
---|
339 | void wined3d_texture_apply_state_changes(struct wined3d_texture *texture,
|
---|
340 | const DWORD sampler_states[WINED3D_HIGHEST_SAMPLER_STATE + 1],
|
---|
341 | const struct wined3d_gl_info *gl_info)
|
---|
342 | {
|
---|
343 | BOOL cond_np2 = texture->flags & WINED3D_TEXTURE_COND_NP2;
|
---|
344 | GLenum target = texture->target;
|
---|
345 | struct gl_texture *gl_tex;
|
---|
346 | DWORD state;
|
---|
347 | DWORD aniso;
|
---|
348 |
|
---|
349 | TRACE("texture %p, sampler_states %p.\n", texture, sampler_states);
|
---|
350 |
|
---|
351 | gl_tex = wined3d_texture_get_gl_texture(texture, gl_info,
|
---|
352 | texture->flags & WINED3D_TEXTURE_IS_SRGB);
|
---|
353 |
|
---|
354 | /* This function relies on the correct texture being bound and loaded. */
|
---|
355 |
|
---|
356 | if (sampler_states[WINED3D_SAMP_ADDRESS_U] != gl_tex->states[WINED3DTEXSTA_ADDRESSU])
|
---|
357 | {
|
---|
358 | state = sampler_states[WINED3D_SAMP_ADDRESS_U];
|
---|
359 | apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_S, cond_np2);
|
---|
360 | gl_tex->states[WINED3DTEXSTA_ADDRESSU] = state;
|
---|
361 | }
|
---|
362 |
|
---|
363 | if (sampler_states[WINED3D_SAMP_ADDRESS_V] != gl_tex->states[WINED3DTEXSTA_ADDRESSV])
|
---|
364 | {
|
---|
365 | state = sampler_states[WINED3D_SAMP_ADDRESS_V];
|
---|
366 | apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_T, cond_np2);
|
---|
367 | gl_tex->states[WINED3DTEXSTA_ADDRESSV] = state;
|
---|
368 | }
|
---|
369 |
|
---|
370 | if (sampler_states[WINED3D_SAMP_ADDRESS_W] != gl_tex->states[WINED3DTEXSTA_ADDRESSW])
|
---|
371 | {
|
---|
372 | state = sampler_states[WINED3D_SAMP_ADDRESS_W];
|
---|
373 | apply_wrap(gl_info, target, state, GL_TEXTURE_WRAP_R, cond_np2);
|
---|
374 | gl_tex->states[WINED3DTEXSTA_ADDRESSW] = state;
|
---|
375 | }
|
---|
376 |
|
---|
377 | if (sampler_states[WINED3D_SAMP_BORDER_COLOR] != gl_tex->states[WINED3DTEXSTA_BORDERCOLOR])
|
---|
378 | {
|
---|
379 | float col[4];
|
---|
380 |
|
---|
381 | state = sampler_states[WINED3D_SAMP_BORDER_COLOR];
|
---|
382 | D3DCOLORTOGLFLOAT4(state, col);
|
---|
383 | TRACE("Setting border color for %#x to %#x.\n", target, state);
|
---|
384 | gl_info->gl_ops.gl.p_glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, &col[0]);
|
---|
385 | checkGLcall("glTexParameterfv(..., GL_TEXTURE_BORDER_COLOR, ...)");
|
---|
386 | gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = state;
|
---|
387 | }
|
---|
388 |
|
---|
389 | if (sampler_states[WINED3D_SAMP_MAG_FILTER] != gl_tex->states[WINED3DTEXSTA_MAGFILTER])
|
---|
390 | {
|
---|
391 | GLint gl_value;
|
---|
392 |
|
---|
393 | state = sampler_states[WINED3D_SAMP_MAG_FILTER];
|
---|
394 | if (state > WINED3D_TEXF_ANISOTROPIC)
|
---|
395 | FIXME("Unrecognized or unsupported MAGFILTER* value %d.\n", state);
|
---|
396 |
|
---|
397 | gl_value = wined3d_gl_mag_filter(texture->mag_lookup,
|
---|
398 | min(max(state, WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR));
|
---|
399 | TRACE("ValueMAG=%#x setting MAGFILTER to %#x.\n", state, gl_value);
|
---|
400 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER, gl_value);
|
---|
401 |
|
---|
402 | gl_tex->states[WINED3DTEXSTA_MAGFILTER] = state;
|
---|
403 | }
|
---|
404 |
|
---|
405 | if ((sampler_states[WINED3D_SAMP_MIN_FILTER] != gl_tex->states[WINED3DTEXSTA_MINFILTER]
|
---|
406 | || sampler_states[WINED3D_SAMP_MIP_FILTER] != gl_tex->states[WINED3DTEXSTA_MIPFILTER]
|
---|
407 | || sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL] != gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL]))
|
---|
408 | {
|
---|
409 | GLint gl_value;
|
---|
410 |
|
---|
411 | gl_tex->states[WINED3DTEXSTA_MIPFILTER] = sampler_states[WINED3D_SAMP_MIP_FILTER];
|
---|
412 | gl_tex->states[WINED3DTEXSTA_MINFILTER] = sampler_states[WINED3D_SAMP_MIN_FILTER];
|
---|
413 | gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL];
|
---|
414 |
|
---|
415 | if (gl_tex->states[WINED3DTEXSTA_MINFILTER] > WINED3D_TEXF_ANISOTROPIC
|
---|
416 | || gl_tex->states[WINED3DTEXSTA_MIPFILTER] > WINED3D_TEXF_ANISOTROPIC)
|
---|
417 | {
|
---|
418 | FIXME("Unrecognized or unsupported MIN_FILTER value %#x MIP_FILTER value %#x.\n",
|
---|
419 | gl_tex->states[WINED3DTEXSTA_MINFILTER],
|
---|
420 | gl_tex->states[WINED3DTEXSTA_MIPFILTER]);
|
---|
421 | }
|
---|
422 | gl_value = wined3d_gl_min_mip_filter(texture->min_mip_lookup,
|
---|
423 | min(max(sampler_states[WINED3D_SAMP_MIN_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR),
|
---|
424 | min(max(sampler_states[WINED3D_SAMP_MIP_FILTER], WINED3D_TEXF_NONE), WINED3D_TEXF_LINEAR));
|
---|
425 |
|
---|
426 | TRACE("ValueMIN=%#x, ValueMIP=%#x, setting MINFILTER to %#x.\n",
|
---|
427 | sampler_states[WINED3D_SAMP_MIN_FILTER],
|
---|
428 | sampler_states[WINED3D_SAMP_MIP_FILTER], gl_value);
|
---|
429 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER, gl_value);
|
---|
430 | checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
|
---|
431 |
|
---|
432 | if (!cond_np2)
|
---|
433 | {
|
---|
434 | if (gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3D_TEXF_NONE)
|
---|
435 | gl_value = texture->lod;
|
---|
436 | else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= texture->level_count)
|
---|
437 | gl_value = texture->level_count - 1;
|
---|
438 | else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < texture->lod)
|
---|
439 | /* texture->lod is already clamped in the setter. */
|
---|
440 | gl_value = texture->lod;
|
---|
441 | else
|
---|
442 | gl_value = gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL];
|
---|
443 |
|
---|
444 | /* Note that WINED3D_SAMP_MAX_MIP_LEVEL specifies the largest mipmap
|
---|
445 | * (default 0), while GL_TEXTURE_MAX_LEVEL specifies the smallest
|
---|
446 | * mimap used (default 1000). So WINED3D_SAMP_MAX_MIP_LEVEL
|
---|
447 | * corresponds to GL_TEXTURE_BASE_LEVEL. */
|
---|
448 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, gl_value);
|
---|
449 | }
|
---|
450 | }
|
---|
451 |
|
---|
452 | if ((gl_tex->states[WINED3DTEXSTA_MAGFILTER] != WINED3D_TEXF_ANISOTROPIC
|
---|
453 | && gl_tex->states[WINED3DTEXSTA_MINFILTER] != WINED3D_TEXF_ANISOTROPIC
|
---|
454 | && gl_tex->states[WINED3DTEXSTA_MIPFILTER] != WINED3D_TEXF_ANISOTROPIC)
|
---|
455 | || cond_np2)
|
---|
456 | aniso = 1;
|
---|
457 | else
|
---|
458 | aniso = sampler_states[WINED3D_SAMP_MAX_ANISOTROPY];
|
---|
459 |
|
---|
460 | if (gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] != aniso)
|
---|
461 | {
|
---|
462 | if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
|
---|
463 | {
|
---|
464 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
|
---|
465 | checkGLcall("glTexParameteri(GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso)");
|
---|
466 | }
|
---|
467 | else
|
---|
468 | {
|
---|
469 | WARN("Anisotropic filtering not supported.\n");
|
---|
470 | }
|
---|
471 | gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso;
|
---|
472 | }
|
---|
473 |
|
---|
474 | /* These should always be the same unless EXT_texture_sRGB_decode is supported. */
|
---|
475 | if (sampler_states[WINED3D_SAMP_SRGB_TEXTURE] != gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE])
|
---|
476 | {
|
---|
477 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_SRGB_DECODE_EXT,
|
---|
478 | sampler_states[WINED3D_SAMP_SRGB_TEXTURE] ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
|
---|
479 | checkGLcall("glTexParameteri(GL_TEXTURE_SRGB_DECODE_EXT)");
|
---|
480 | gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = sampler_states[WINED3D_SAMP_SRGB_TEXTURE];
|
---|
481 | }
|
---|
482 |
|
---|
483 | if (!(texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW)
|
---|
484 | != !gl_tex->states[WINED3DTEXSTA_SHADOW])
|
---|
485 | {
|
---|
486 | if (texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW)
|
---|
487 | {
|
---|
488 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
|
---|
489 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
|
---|
490 | checkGLcall("glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB)");
|
---|
491 | gl_tex->states[WINED3DTEXSTA_SHADOW] = TRUE;
|
---|
492 | }
|
---|
493 | else
|
---|
494 | {
|
---|
495 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
|
---|
496 | checkGLcall("glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE)");
|
---|
497 | gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
|
---|
498 | }
|
---|
499 | }
|
---|
500 | }
|
---|
501 |
|
---|
502 | ULONG CDECL wined3d_texture_incref(struct wined3d_texture *texture)
|
---|
503 | {
|
---|
504 | ULONG refcount = InterlockedIncrement(&texture->resource.ref);
|
---|
505 |
|
---|
506 | TRACE("%p increasing refcount to %u.\n", texture, refcount);
|
---|
507 |
|
---|
508 | return refcount;
|
---|
509 | }
|
---|
510 |
|
---|
511 | /* Do not call while under the GL lock. */
|
---|
512 | ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture)
|
---|
513 | {
|
---|
514 | ULONG refcount = InterlockedDecrement(&texture->resource.ref);
|
---|
515 |
|
---|
516 | TRACE("%p decreasing refcount to %u.\n", texture, refcount);
|
---|
517 |
|
---|
518 | if (!refcount)
|
---|
519 | {
|
---|
520 | wined3d_texture_cleanup(texture);
|
---|
521 | texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);
|
---|
522 | HeapFree(GetProcessHeap(), 0, texture);
|
---|
523 | }
|
---|
524 |
|
---|
525 | return refcount;
|
---|
526 | }
|
---|
527 |
|
---|
528 | struct wined3d_resource * CDECL wined3d_texture_get_resource(struct wined3d_texture *texture)
|
---|
529 | {
|
---|
530 | TRACE("texture %p.\n", texture);
|
---|
531 |
|
---|
532 | return &texture->resource;
|
---|
533 | }
|
---|
534 |
|
---|
535 | DWORD CDECL wined3d_texture_set_priority(struct wined3d_texture *texture, DWORD priority)
|
---|
536 | {
|
---|
537 | return resource_set_priority(&texture->resource, priority);
|
---|
538 | }
|
---|
539 |
|
---|
540 | DWORD CDECL wined3d_texture_get_priority(const struct wined3d_texture *texture)
|
---|
541 | {
|
---|
542 | return resource_get_priority(&texture->resource);
|
---|
543 | }
|
---|
544 |
|
---|
545 | /* Do not call while under the GL lock. */
|
---|
546 | void CDECL wined3d_texture_preload(struct wined3d_texture *texture)
|
---|
547 | {
|
---|
548 | texture->texture_ops->texture_preload(texture, SRGB_ANY);
|
---|
549 | }
|
---|
550 |
|
---|
551 | void * CDECL wined3d_texture_get_parent(const struct wined3d_texture *texture)
|
---|
552 | {
|
---|
553 | TRACE("texture %p.\n", texture);
|
---|
554 |
|
---|
555 | return texture->resource.parent;
|
---|
556 | }
|
---|
557 |
|
---|
558 | DWORD CDECL wined3d_texture_set_lod(struct wined3d_texture *texture, DWORD lod)
|
---|
559 | {
|
---|
560 | DWORD old = texture->lod;
|
---|
561 |
|
---|
562 | TRACE("texture %p, lod %u.\n", texture, lod);
|
---|
563 |
|
---|
564 | /* The d3d9:texture test shows that SetLOD is ignored on non-managed
|
---|
565 | * textures. The call always returns 0, and GetLOD always returns 0. */
|
---|
566 | if (texture->resource.pool != WINED3D_POOL_MANAGED)
|
---|
567 | {
|
---|
568 | TRACE("Ignoring SetLOD on %s texture, returning 0.\n", debug_d3dpool(texture->resource.pool));
|
---|
569 | return 0;
|
---|
570 | }
|
---|
571 |
|
---|
572 | if (lod >= texture->level_count)
|
---|
573 | lod = texture->level_count - 1;
|
---|
574 |
|
---|
575 | if (texture->lod != lod)
|
---|
576 | {
|
---|
577 | texture->lod = lod;
|
---|
578 |
|
---|
579 | texture->texture_rgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U;
|
---|
580 | texture->texture_srgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U;
|
---|
581 | if (texture->resource.bind_count)
|
---|
582 | device_invalidate_state(texture->resource.device, STATE_SAMPLER(texture->sampler));
|
---|
583 | }
|
---|
584 |
|
---|
585 | return old;
|
---|
586 | }
|
---|
587 |
|
---|
588 | DWORD CDECL wined3d_texture_get_lod(const struct wined3d_texture *texture)
|
---|
589 | {
|
---|
590 | TRACE("texture %p, returning %u.\n", texture, texture->lod);
|
---|
591 |
|
---|
592 | return texture->lod;
|
---|
593 | }
|
---|
594 |
|
---|
595 | DWORD CDECL wined3d_texture_get_level_count(const struct wined3d_texture *texture)
|
---|
596 | {
|
---|
597 | TRACE("texture %p, returning %u.\n", texture, texture->level_count);
|
---|
598 |
|
---|
599 | return texture->level_count;
|
---|
600 | }
|
---|
601 |
|
---|
602 | HRESULT CDECL wined3d_texture_set_autogen_filter_type(struct wined3d_texture *texture,
|
---|
603 | enum wined3d_texture_filter_type filter_type)
|
---|
604 | {
|
---|
605 | FIXME("texture %p, filter_type %s stub!\n", texture, debug_d3dtexturefiltertype(filter_type));
|
---|
606 |
|
---|
607 | if (!(texture->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP))
|
---|
608 | {
|
---|
609 | WARN("Texture doesn't have AUTOGENMIPMAP usage.\n");
|
---|
610 | return WINED3DERR_INVALIDCALL;
|
---|
611 | }
|
---|
612 |
|
---|
613 | texture->filter_type = filter_type;
|
---|
614 |
|
---|
615 | return WINED3D_OK;
|
---|
616 | }
|
---|
617 |
|
---|
618 | enum wined3d_texture_filter_type CDECL wined3d_texture_get_autogen_filter_type(const struct wined3d_texture *texture)
|
---|
619 | {
|
---|
620 | TRACE("texture %p.\n", texture);
|
---|
621 |
|
---|
622 | return texture->filter_type;
|
---|
623 | }
|
---|
624 |
|
---|
625 | void CDECL wined3d_texture_generate_mipmaps(struct wined3d_texture *texture)
|
---|
626 | {
|
---|
627 | /* TODO: Implement filters using GL_SGI_generate_mipmaps. */
|
---|
628 | FIXME("texture %p stub!\n", texture);
|
---|
629 | }
|
---|
630 |
|
---|
631 | struct wined3d_resource * CDECL wined3d_texture_get_sub_resource(struct wined3d_texture *texture,
|
---|
632 | UINT sub_resource_idx)
|
---|
633 | {
|
---|
634 | UINT sub_count = texture->level_count * texture->layer_count;
|
---|
635 |
|
---|
636 | TRACE("texture %p, sub_resource_idx %u.\n", texture, sub_resource_idx);
|
---|
637 |
|
---|
638 | if (sub_resource_idx >= sub_count)
|
---|
639 | {
|
---|
640 | WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx, sub_count);
|
---|
641 | return NULL;
|
---|
642 | }
|
---|
643 |
|
---|
644 | return texture->sub_resources[sub_resource_idx];
|
---|
645 | }
|
---|
646 |
|
---|
647 | HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
|
---|
648 | UINT layer, const struct wined3d_box *dirty_region)
|
---|
649 | {
|
---|
650 | struct wined3d_resource *sub_resource;
|
---|
651 |
|
---|
652 | TRACE("texture %p, layer %u, dirty_region %p.\n", texture, layer, dirty_region);
|
---|
653 |
|
---|
654 | if (!(sub_resource = wined3d_texture_get_sub_resource(texture, layer * texture->level_count)))
|
---|
655 | {
|
---|
656 | WARN("Failed to get sub-resource.\n");
|
---|
657 | return WINED3DERR_INVALIDCALL;
|
---|
658 | }
|
---|
659 |
|
---|
660 | wined3d_texture_set_dirty(texture, TRUE);
|
---|
661 | texture->texture_ops->texture_sub_resource_add_dirty_region(sub_resource, dirty_region);
|
---|
662 |
|
---|
663 | return WINED3D_OK;
|
---|
664 | }
|
---|
665 |
|
---|
666 | /* Context activation is done by the caller. */
|
---|
667 | static HRESULT texture2d_bind(struct wined3d_texture *texture,
|
---|
668 | struct wined3d_context *context, BOOL srgb)
|
---|
669 | {
|
---|
670 | const struct wined3d_gl_info *gl_info = context->gl_info;
|
---|
671 | BOOL set_gl_texture_desc;
|
---|
672 | HRESULT hr;
|
---|
673 |
|
---|
674 | TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
|
---|
675 |
|
---|
676 | hr = wined3d_texture_bind(texture, context, srgb, &set_gl_texture_desc);
|
---|
677 | if (set_gl_texture_desc && SUCCEEDED(hr))
|
---|
678 | {
|
---|
679 | UINT sub_count = texture->level_count * texture->layer_count;
|
---|
680 | BOOL srgb_tex = !context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
|
---|
681 | && (texture->flags & WINED3D_TEXTURE_IS_SRGB);
|
---|
682 | struct gl_texture *gl_tex;
|
---|
683 | UINT i;
|
---|
684 |
|
---|
685 | gl_tex = wined3d_texture_get_gl_texture(texture, context->gl_info, srgb_tex);
|
---|
686 |
|
---|
687 | for (i = 0; i < sub_count; ++i)
|
---|
688 | {
|
---|
689 | struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
|
---|
690 | surface_set_texture_name(surface, gl_tex->name, srgb_tex);
|
---|
691 | }
|
---|
692 |
|
---|
693 | /* Conditinal non power of two textures use a different clamping
|
---|
694 | * default. If we're using the GL_WINE_normalized_texrect partial
|
---|
695 | * driver emulation, we're dealing with a GL_TEXTURE_2D texture which
|
---|
696 | * has the address mode set to repeat - something that prevents us
|
---|
697 | * from hitting the accelerated codepath. Thus manually set the GL
|
---|
698 | * state. The same applies to filtering. Even if the texture has only
|
---|
699 | * one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW
|
---|
700 | * fallback on macos. */
|
---|
701 | if (texture->flags & WINED3D_TEXTURE_COND_NP2)
|
---|
702 | {
|
---|
703 | #ifdef VBOX_WITH_WDDM
|
---|
704 | Assert(!VBOXSHRC_IS_SHARED_OPENED(texture));
|
---|
705 | if (!VBOXSHRC_IS_SHARED_OPENED(texture))
|
---|
706 | #endif
|
---|
707 | {
|
---|
708 | GLenum target = texture->target;
|
---|
709 |
|
---|
710 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
---|
711 | checkGLcall("glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)");
|
---|
712 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
---|
713 | checkGLcall("glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)");
|
---|
714 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
---|
715 | checkGLcall("glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)");
|
---|
716 | gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
---|
717 | checkGLcall("glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)");
|
---|
718 | }
|
---|
719 | gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_CLAMP;
|
---|
720 | gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_CLAMP;
|
---|
721 | gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT;
|
---|
722 | gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT;
|
---|
723 | gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE;
|
---|
724 | }
|
---|
725 | }
|
---|
726 |
|
---|
727 | return hr;
|
---|
728 | }
|
---|
729 |
|
---|
730 | static BOOL texture_srgb_mode(const struct wined3d_texture *texture, enum WINED3DSRGB srgb)
|
---|
731 | {
|
---|
732 | switch (srgb)
|
---|
733 | {
|
---|
734 | case SRGB_RGB:
|
---|
735 | return FALSE;
|
---|
736 |
|
---|
737 | case SRGB_SRGB:
|
---|
738 | return TRUE;
|
---|
739 |
|
---|
740 | default:
|
---|
741 | return texture->flags & WINED3D_TEXTURE_IS_SRGB;
|
---|
742 | }
|
---|
743 | }
|
---|
744 |
|
---|
745 | /* Do not call while under the GL lock. */
|
---|
746 | static void texture2d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb)
|
---|
747 | {
|
---|
748 | UINT sub_count = texture->level_count * texture->layer_count;
|
---|
749 | struct wined3d_device *device = texture->resource.device;
|
---|
750 | const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
---|
751 | struct wined3d_context *context = NULL;
|
---|
752 | struct gl_texture *gl_tex;
|
---|
753 | BOOL srgb_mode;
|
---|
754 | UINT i;
|
---|
755 |
|
---|
756 | TRACE("texture %p, srgb %#x.\n", texture, srgb);
|
---|
757 |
|
---|
758 | srgb_mode = texture_srgb_mode(texture, srgb);
|
---|
759 | gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, srgb_mode);
|
---|
760 |
|
---|
761 | if (!device->isInDraw)
|
---|
762 | {
|
---|
763 | /* No danger of recursive calls, context_acquire() sets isInDraw to TRUE
|
---|
764 | * when loading offscreen render targets into the texture. */
|
---|
765 | context = context_acquire(device, NULL);
|
---|
766 | }
|
---|
767 |
|
---|
768 | if (gl_tex->dirty)
|
---|
769 | {
|
---|
770 | /* Reload the surfaces if the texture is marked dirty. */
|
---|
771 | for (i = 0; i < sub_count; ++i)
|
---|
772 | {
|
---|
773 | surface_load(surface_from_resource(texture->sub_resources[i]), srgb_mode);
|
---|
774 | }
|
---|
775 | }
|
---|
776 | else
|
---|
777 | {
|
---|
778 | TRACE("Texture %p not dirty, nothing to do.\n", texture);
|
---|
779 | }
|
---|
780 |
|
---|
781 | /* No longer dirty. */
|
---|
782 | gl_tex->dirty = FALSE;
|
---|
783 |
|
---|
784 | if (context) context_release(context);
|
---|
785 | }
|
---|
786 |
|
---|
787 | static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource,
|
---|
788 | const struct wined3d_box *dirty_region)
|
---|
789 | {
|
---|
790 | surface_add_dirty_rect(surface_from_resource(sub_resource), dirty_region);
|
---|
791 | }
|
---|
792 |
|
---|
793 | static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource)
|
---|
794 | {
|
---|
795 | struct wined3d_surface *surface = surface_from_resource(sub_resource);
|
---|
796 |
|
---|
797 | /* Clean out the texture name we gave to the surface so that the
|
---|
798 | * surface doesn't try and release it. */
|
---|
799 | surface_set_texture_name(surface, 0, TRUE);
|
---|
800 | surface_set_texture_name(surface, 0, FALSE);
|
---|
801 | surface_set_texture_target(surface, 0, 0);
|
---|
802 | surface_set_container(surface, NULL);
|
---|
803 | wined3d_surface_decref(surface);
|
---|
804 | }
|
---|
805 |
|
---|
806 | /* Do not call while under the GL lock. */
|
---|
807 | static void texture2d_unload(struct wined3d_resource *resource)
|
---|
808 | {
|
---|
809 | struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
|
---|
810 | UINT sub_count = texture->level_count * texture->layer_count;
|
---|
811 | UINT i;
|
---|
812 |
|
---|
813 | TRACE("texture %p.\n", texture);
|
---|
814 |
|
---|
815 | for (i = 0; i < sub_count; ++i)
|
---|
816 | {
|
---|
817 | struct wined3d_resource *sub_resource = texture->sub_resources[i];
|
---|
818 | struct wined3d_surface *surface = surface_from_resource(sub_resource);
|
---|
819 |
|
---|
820 | sub_resource->resource_ops->resource_unload(sub_resource);
|
---|
821 | surface_set_texture_name(surface, 0, FALSE); /* Delete RGB name */
|
---|
822 | surface_set_texture_name(surface, 0, TRUE); /* Delete sRGB name */
|
---|
823 | }
|
---|
824 |
|
---|
825 | wined3d_texture_unload(texture);
|
---|
826 | }
|
---|
827 |
|
---|
828 | static const struct wined3d_texture_ops texture2d_ops =
|
---|
829 | {
|
---|
830 | texture2d_bind,
|
---|
831 | texture2d_preload,
|
---|
832 | texture2d_sub_resource_add_dirty_region,
|
---|
833 | texture2d_sub_resource_cleanup,
|
---|
834 | };
|
---|
835 |
|
---|
836 | static const struct wined3d_resource_ops texture2d_resource_ops =
|
---|
837 | {
|
---|
838 | texture2d_unload,
|
---|
839 | };
|
---|
840 |
|
---|
841 | static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
|
---|
842 | UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
|
---|
843 | const struct wined3d_parent_ops *parent_ops
|
---|
844 | #ifdef VBOX_WITH_WDDM
|
---|
845 | , HANDLE *shared_handle
|
---|
846 | , void **pavClientMem
|
---|
847 | #endif
|
---|
848 | )
|
---|
849 | {
|
---|
850 | const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
---|
851 | struct wined3d_resource_desc surface_desc;
|
---|
852 | unsigned int i, j;
|
---|
853 | HRESULT hr;
|
---|
854 |
|
---|
855 | /* TODO: It should only be possible to create textures for formats
|
---|
856 | * that are reported as supported. */
|
---|
857 | if (WINED3DFMT_UNKNOWN >= desc->format)
|
---|
858 | {
|
---|
859 | WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
|
---|
860 | return WINED3DERR_INVALIDCALL;
|
---|
861 | }
|
---|
862 |
|
---|
863 | if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && desc->pool != WINED3D_POOL_SCRATCH)
|
---|
864 | {
|
---|
865 | WARN("(%p) : Tried to create not supported cube texture.\n", texture);
|
---|
866 | return WINED3DERR_INVALIDCALL;
|
---|
867 | }
|
---|
868 |
|
---|
869 | /* Calculate levels for mip mapping */
|
---|
870 | if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
|
---|
871 | {
|
---|
872 | if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
|
---|
873 | {
|
---|
874 | WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n");
|
---|
875 | return WINED3DERR_INVALIDCALL;
|
---|
876 | }
|
---|
877 |
|
---|
878 | if (levels > 1)
|
---|
879 | {
|
---|
880 | WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n");
|
---|
881 | return WINED3DERR_INVALIDCALL;
|
---|
882 | }
|
---|
883 |
|
---|
884 | levels = 1;
|
---|
885 | }
|
---|
886 | else if (!levels)
|
---|
887 | {
|
---|
888 | levels = wined3d_log2i(desc->width) + 1;
|
---|
889 | TRACE("Calculated levels = %u.\n", levels);
|
---|
890 | }
|
---|
891 |
|
---|
892 | if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
|
---|
893 | {
|
---|
894 | UINT pow2_edge_length = 1;
|
---|
895 | while (pow2_edge_length < desc->width)
|
---|
896 | pow2_edge_length <<= 1;
|
---|
897 |
|
---|
898 | if (desc->width != pow2_edge_length)
|
---|
899 | {
|
---|
900 | if (desc->pool == WINED3D_POOL_SCRATCH)
|
---|
901 | {
|
---|
902 | /* SCRATCH textures cannot be used for texturing */
|
---|
903 | WARN("Creating a scratch NPOT cube texture despite lack of HW support.\n");
|
---|
904 | }
|
---|
905 | else
|
---|
906 | {
|
---|
907 | WARN("Attempted to create a NPOT cube texture (edge length %u) without GL support.\n", desc->width);
|
---|
908 | return WINED3DERR_INVALIDCALL;
|
---|
909 | }
|
---|
910 | }
|
---|
911 | }
|
---|
912 |
|
---|
913 | #ifdef VBOX_WITH_WDDM
|
---|
914 | if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels,
|
---|
915 | desc, device, parent, parent_ops, &texture2d_resource_ops,
|
---|
916 | shared_handle, pavClientMem)))
|
---|
917 | #else
|
---|
918 | if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels,
|
---|
919 | desc, device, parent, parent_ops, &texture2d_resource_ops)))
|
---|
920 | #endif
|
---|
921 | {
|
---|
922 | WARN("Failed to initialize texture, returning %#x\n", hr);
|
---|
923 | return hr;
|
---|
924 | }
|
---|
925 |
|
---|
926 | texture->pow2_matrix[0] = 1.0f;
|
---|
927 | texture->pow2_matrix[5] = 1.0f;
|
---|
928 | texture->pow2_matrix[10] = 1.0f;
|
---|
929 | texture->pow2_matrix[15] = 1.0f;
|
---|
930 | texture->target = GL_TEXTURE_CUBE_MAP_ARB;
|
---|
931 |
|
---|
932 | /* Generate all the surfaces. */
|
---|
933 | surface_desc = *desc;
|
---|
934 | surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
|
---|
935 | for (i = 0; i < texture->level_count; ++i)
|
---|
936 | {
|
---|
937 | /* Create the 6 faces. */
|
---|
938 | for (j = 0; j < 6; ++j)
|
---|
939 | {
|
---|
940 | static const GLenum cube_targets[6] =
|
---|
941 | {
|
---|
942 | GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
|
---|
943 | GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
|
---|
944 | GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
|
---|
945 | GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
|
---|
946 | GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
|
---|
947 | GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
|
---|
948 | };
|
---|
949 | UINT idx = j * texture->level_count + i;
|
---|
950 | struct wined3d_surface *surface;
|
---|
951 |
|
---|
952 |
|
---|
953 | #ifdef VBOX_WITH_WDDM
|
---|
954 | if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
|
---|
955 | parent, &surface_desc, idx, surface_flags, &surface
|
---|
956 | ,NULL, pavClientMem ? pavClientMem[i * 6 + j] : NULL
|
---|
957 | )))
|
---|
958 | #else
|
---|
959 | if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
|
---|
960 | parent, &surface_desc, idx, surface_flags, &surface)))
|
---|
961 | #endif
|
---|
962 | {
|
---|
963 | FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr);
|
---|
964 | wined3d_texture_cleanup(texture);
|
---|
965 | return hr;
|
---|
966 | }
|
---|
967 |
|
---|
968 | surface_set_container(surface, texture);
|
---|
969 | surface_set_texture_target(surface, cube_targets[j], i);
|
---|
970 | texture->sub_resources[idx] = &surface->resource;
|
---|
971 | TRACE("Created surface level %u @ %p.\n", i, surface);
|
---|
972 | }
|
---|
973 | surface_desc.width = max(1, surface_desc.width >> 1);
|
---|
974 | surface_desc.height = surface_desc.width;
|
---|
975 | }
|
---|
976 |
|
---|
977 | #ifdef VBOX_WITH_WDDM
|
---|
978 | if (VBOXSHRC_IS_SHARED(texture))
|
---|
979 | {
|
---|
980 | Assert(shared_handle);
|
---|
981 | for (i = 0; i < texture->level_count; ++i)
|
---|
982 | {
|
---|
983 | for (j = 0; j < 6; ++j)
|
---|
984 | {
|
---|
985 | UINT idx = j * texture->level_count + i;
|
---|
986 | VBOXSHRC_COPY_SHAREDATA(surface_from_resource(texture->sub_resources[idx]), texture);
|
---|
987 | }
|
---|
988 | }
|
---|
989 | #ifdef DEBUG
|
---|
990 | for (i = 0; i < texture->level_count; ++i)
|
---|
991 | {
|
---|
992 | for (j = 0; j < 6; ++j)
|
---|
993 | {
|
---|
994 | UINT idx = j * texture->level_count + i;
|
---|
995 | Assert(!surface_from_resource(texture->sub_resources[idx])->texture_name);
|
---|
996 | }
|
---|
997 | }
|
---|
998 | #endif
|
---|
999 |
|
---|
1000 | if (!VBOXSHRC_IS_SHARED_OPENED(texture))
|
---|
1001 | {
|
---|
1002 | for (i = 0; i < texture->level_count; ++i)
|
---|
1003 | {
|
---|
1004 | for (j = 0; j < 6; ++j)
|
---|
1005 | {
|
---|
1006 | UINT idx = j * texture->level_count + i;
|
---|
1007 | struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[idx]);
|
---|
1008 | surface_load_location(surface, SFLAG_INTEXTURE, NULL);
|
---|
1009 | }
|
---|
1010 | }
|
---|
1011 |
|
---|
1012 | Assert(!(*shared_handle));
|
---|
1013 | *shared_handle = VBOXSHRC_GET_SHAREHANDLE(texture);
|
---|
1014 | }
|
---|
1015 | else
|
---|
1016 | {
|
---|
1017 | struct wined3d_context *context = NULL;
|
---|
1018 | const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
---|
1019 | struct gl_texture *gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, FALSE);
|
---|
1020 | texture->texture_rgb.name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
|
---|
1021 | gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
|
---|
1022 | gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
|
---|
1023 | gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
|
---|
1024 | gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
|
---|
1025 | gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
|
---|
1026 | gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
|
---|
1027 | gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
|
---|
1028 | gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
|
---|
1029 | gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
|
---|
1030 | if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
|
---|
1031 | gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
|
---|
1032 | else
|
---|
1033 | gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = FALSE;
|
---|
1034 | gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
|
---|
1035 | wined3d_texture_set_dirty(texture, TRUE);
|
---|
1036 |
|
---|
1037 | context = context_acquire(device, NULL);
|
---|
1038 | pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
|
---|
1039 | context_release(context);
|
---|
1040 |
|
---|
1041 | for (i = 0; i < texture->level_count; ++i)
|
---|
1042 | {
|
---|
1043 | for (j = 0; j < 6; ++j)
|
---|
1044 | {
|
---|
1045 | UINT idx = j * texture->level_count + i;
|
---|
1046 | struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[idx]);
|
---|
1047 | surface_setup_location_onopen(surface);
|
---|
1048 | Assert(*shared_handle);
|
---|
1049 | Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture));
|
---|
1050 | }
|
---|
1051 | }
|
---|
1052 | }
|
---|
1053 | #ifdef DEBUG
|
---|
1054 | for (i = 0; i < texture->level_count; ++i)
|
---|
1055 | {
|
---|
1056 | for (j = 0; j < 6; ++j)
|
---|
1057 | {
|
---|
1058 | UINT idx = j * texture->level_count + i;
|
---|
1059 | Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[idx])->texture_name);
|
---|
1060 | }
|
---|
1061 | }
|
---|
1062 | #endif
|
---|
1063 |
|
---|
1064 | #ifdef DEBUG
|
---|
1065 | for (i = 0; i < texture->level_count; ++i)
|
---|
1066 | {
|
---|
1067 | for (j = 0; j < 6; ++j)
|
---|
1068 | {
|
---|
1069 | UINT idx = j * texture->level_count + i;
|
---|
1070 | Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[idx])->texture_name);
|
---|
1071 | }
|
---|
1072 | }
|
---|
1073 | #endif
|
---|
1074 |
|
---|
1075 | Assert(!device->isInDraw);
|
---|
1076 |
|
---|
1077 | /* flush to ensure the texture is allocated/referenced before it is used/released by another
|
---|
1078 | * process opening/creating it */
|
---|
1079 | Assert(device->context_count == 1);
|
---|
1080 | pVBoxFlushToHost(device->contexts[0]->glCtx);
|
---|
1081 | }
|
---|
1082 | else
|
---|
1083 | {
|
---|
1084 | Assert(!shared_handle);
|
---|
1085 | }
|
---|
1086 | #endif
|
---|
1087 |
|
---|
1088 | return WINED3D_OK;
|
---|
1089 | }
|
---|
1090 |
|
---|
1091 | static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
|
---|
1092 | UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
|
---|
1093 | const struct wined3d_parent_ops *parent_ops
|
---|
1094 | #ifdef VBOX_WITH_WDDM
|
---|
1095 | , HANDLE *shared_handle
|
---|
1096 | , void **pavClientMem
|
---|
1097 | #endif
|
---|
1098 | )
|
---|
1099 | {
|
---|
1100 | const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
---|
1101 | struct wined3d_resource_desc surface_desc;
|
---|
1102 | UINT pow2_width, pow2_height;
|
---|
1103 | unsigned int i;
|
---|
1104 | HRESULT hr;
|
---|
1105 |
|
---|
1106 | /* TODO: It should only be possible to create textures for formats
|
---|
1107 | * that are reported as supported. */
|
---|
1108 | if (WINED3DFMT_UNKNOWN >= desc->format)
|
---|
1109 | {
|
---|
1110 | WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
|
---|
1111 | return WINED3DERR_INVALIDCALL;
|
---|
1112 | }
|
---|
1113 |
|
---|
1114 | /* Non-power2 support. */
|
---|
1115 | if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
|
---|
1116 | {
|
---|
1117 | pow2_width = desc->width;
|
---|
1118 | pow2_height = desc->height;
|
---|
1119 | }
|
---|
1120 | else
|
---|
1121 | {
|
---|
1122 | /* Find the nearest pow2 match. */
|
---|
1123 | pow2_width = pow2_height = 1;
|
---|
1124 | while (pow2_width < desc->width)
|
---|
1125 | pow2_width <<= 1;
|
---|
1126 | while (pow2_height < desc->height)
|
---|
1127 | pow2_height <<= 1;
|
---|
1128 |
|
---|
1129 | if (pow2_width != desc->width || pow2_height != desc->height)
|
---|
1130 | {
|
---|
1131 | /* levels == 0 returns an error as well */
|
---|
1132 | if (levels != 1)
|
---|
1133 | {
|
---|
1134 | if (desc->pool == WINED3D_POOL_SCRATCH)
|
---|
1135 | {
|
---|
1136 | WARN("Creating a scratch mipmapped NPOT texture despite lack of HW support.\n");
|
---|
1137 | }
|
---|
1138 | else
|
---|
1139 | {
|
---|
1140 | WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n");
|
---|
1141 | return WINED3DERR_INVALIDCALL;
|
---|
1142 | }
|
---|
1143 | }
|
---|
1144 | }
|
---|
1145 | }
|
---|
1146 |
|
---|
1147 | /* Calculate levels for mip mapping. */
|
---|
1148 | if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
|
---|
1149 | {
|
---|
1150 | if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
|
---|
1151 | {
|
---|
1152 | WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n");
|
---|
1153 | return WINED3DERR_INVALIDCALL;
|
---|
1154 | }
|
---|
1155 |
|
---|
1156 | if (levels > 1)
|
---|
1157 | {
|
---|
1158 | WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n");
|
---|
1159 | return WINED3DERR_INVALIDCALL;
|
---|
1160 | }
|
---|
1161 |
|
---|
1162 | levels = 1;
|
---|
1163 | }
|
---|
1164 | else if (!levels)
|
---|
1165 | {
|
---|
1166 | levels = wined3d_log2i(max(desc->width, desc->height)) + 1;
|
---|
1167 | TRACE("Calculated levels = %u.\n", levels);
|
---|
1168 | }
|
---|
1169 |
|
---|
1170 | #ifdef VBOX_WITH_WDDM
|
---|
1171 | if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
|
---|
1172 | desc, device, parent, parent_ops, &texture2d_resource_ops,
|
---|
1173 | shared_handle, pavClientMem)))
|
---|
1174 | #else
|
---|
1175 | if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
|
---|
1176 | desc, device, parent, parent_ops, &texture2d_resource_ops)))
|
---|
1177 | #endif
|
---|
1178 | {
|
---|
1179 | WARN("Failed to initialize texture, returning %#x.\n", hr);
|
---|
1180 | return hr;
|
---|
1181 | }
|
---|
1182 |
|
---|
1183 | /* Precalculated scaling for 'faked' non power of two texture coords.
|
---|
1184 | * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
|
---|
1185 | * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE
|
---|
1186 | * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */
|
---|
1187 | if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]
|
---|
1188 | && (desc->width != pow2_width || desc->height != pow2_height))
|
---|
1189 | {
|
---|
1190 | texture->pow2_matrix[0] = 1.0f;
|
---|
1191 | texture->pow2_matrix[5] = 1.0f;
|
---|
1192 | texture->pow2_matrix[10] = 1.0f;
|
---|
1193 | texture->pow2_matrix[15] = 1.0f;
|
---|
1194 | texture->target = GL_TEXTURE_2D;
|
---|
1195 | texture->flags |= WINED3D_TEXTURE_COND_NP2;
|
---|
1196 | texture->min_mip_lookup = minMipLookup_noFilter;
|
---|
1197 | }
|
---|
1198 | else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (desc->width != pow2_width || desc->height != pow2_height)
|
---|
1199 | && !(desc->format == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE]
|
---|
1200 | && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
|
---|
1201 | {
|
---|
1202 | texture->pow2_matrix[0] = (float)desc->width;
|
---|
1203 | texture->pow2_matrix[5] = (float)desc->height;
|
---|
1204 | texture->pow2_matrix[10] = 1.0f;
|
---|
1205 | texture->pow2_matrix[15] = 1.0f;
|
---|
1206 | texture->target = GL_TEXTURE_RECTANGLE_ARB;
|
---|
1207 | texture->flags |= WINED3D_TEXTURE_COND_NP2;
|
---|
1208 | texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
|
---|
1209 |
|
---|
1210 | if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
|
---|
1211 | texture->min_mip_lookup = minMipLookup_noMip;
|
---|
1212 | else
|
---|
1213 | texture->min_mip_lookup = minMipLookup_noFilter;
|
---|
1214 | }
|
---|
1215 | else
|
---|
1216 | {
|
---|
1217 | if ((desc->width != pow2_width) || (desc->height != pow2_height))
|
---|
1218 | {
|
---|
1219 | texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width));
|
---|
1220 | texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height));
|
---|
1221 | texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
|
---|
1222 | }
|
---|
1223 | else
|
---|
1224 | {
|
---|
1225 | texture->pow2_matrix[0] = 1.0f;
|
---|
1226 | texture->pow2_matrix[5] = 1.0f;
|
---|
1227 | }
|
---|
1228 |
|
---|
1229 | texture->pow2_matrix[10] = 1.0f;
|
---|
1230 | texture->pow2_matrix[15] = 1.0f;
|
---|
1231 | texture->target = GL_TEXTURE_2D;
|
---|
1232 | }
|
---|
1233 | TRACE("xf(%f) yf(%f)\n", texture->pow2_matrix[0], texture->pow2_matrix[5]);
|
---|
1234 |
|
---|
1235 | /* Generate all the surfaces. */
|
---|
1236 | surface_desc = *desc;
|
---|
1237 | surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
|
---|
1238 | for (i = 0; i < texture->level_count; ++i)
|
---|
1239 | {
|
---|
1240 | struct wined3d_surface *surface;
|
---|
1241 |
|
---|
1242 | /* Use the callback to create the texture surface. */
|
---|
1243 | #ifdef VBOX_WITH_WDDM
|
---|
1244 | if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
|
---|
1245 | parent, &surface_desc, i, surface_flags, &surface
|
---|
1246 | , NULL /* <- we first create a surface in an average "non-shared" fashion and initialize its share properties later (see below)
|
---|
1247 | * this is done this way because the surface does not have its parent (texture) setup properly
|
---|
1248 | * thus we can not initialize texture at this stage */
|
---|
1249 | , pavClientMem ? pavClientMem[i] : NULL
|
---|
1250 | )))
|
---|
1251 | #else
|
---|
1252 | if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
|
---|
1253 | parent, &surface_desc, i, surface_flags, &surface)))
|
---|
1254 | #endif
|
---|
1255 | {
|
---|
1256 | FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
|
---|
1257 | wined3d_texture_cleanup(texture);
|
---|
1258 | return hr;
|
---|
1259 | }
|
---|
1260 |
|
---|
1261 | surface_set_container(surface, texture);
|
---|
1262 | surface_set_texture_target(surface, texture->target, i);
|
---|
1263 | texture->sub_resources[i] = &surface->resource;
|
---|
1264 | TRACE("Created surface level %u @ %p.\n", i, surface);
|
---|
1265 | /* Calculate the next mipmap level. */
|
---|
1266 | surface_desc.width = max(1, surface_desc.width >> 1);
|
---|
1267 | surface_desc.height = max(1, surface_desc.height >> 1);
|
---|
1268 | }
|
---|
1269 |
|
---|
1270 | #ifdef VBOX_WITH_WDDM
|
---|
1271 | if (VBOXSHRC_IS_SHARED(texture))
|
---|
1272 | {
|
---|
1273 | Assert(shared_handle);
|
---|
1274 | for (i = 0; i < texture->level_count; ++i)
|
---|
1275 | {
|
---|
1276 | VBOXSHRC_COPY_SHAREDATA(surface_from_resource(texture->sub_resources[i]), texture);
|
---|
1277 | }
|
---|
1278 | #ifdef DEBUG
|
---|
1279 | for (i = 0; i < texture->level_count; ++i)
|
---|
1280 | {
|
---|
1281 | Assert(!surface_from_resource(texture->sub_resources[i])->texture_name);
|
---|
1282 | }
|
---|
1283 | #endif
|
---|
1284 | if (!VBOXSHRC_IS_SHARED_OPENED(texture))
|
---|
1285 | {
|
---|
1286 | for (i = 0; i < texture->level_count; ++i)
|
---|
1287 | {
|
---|
1288 | struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
|
---|
1289 | surface_load_location(surface, SFLAG_INTEXTURE, NULL);
|
---|
1290 | }
|
---|
1291 |
|
---|
1292 | Assert(!(*shared_handle));
|
---|
1293 | *shared_handle = VBOXSHRC_GET_SHAREHANDLE(texture);
|
---|
1294 | }
|
---|
1295 | else
|
---|
1296 | {
|
---|
1297 | struct wined3d_context *context = NULL;
|
---|
1298 | const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
---|
1299 | struct gl_texture *gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, FALSE);
|
---|
1300 | texture->texture_rgb.name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
|
---|
1301 | gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
|
---|
1302 | gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
|
---|
1303 | gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
|
---|
1304 | gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
|
---|
1305 | gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
|
---|
1306 | gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
|
---|
1307 | gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
|
---|
1308 | gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
|
---|
1309 | gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
|
---|
1310 | if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
|
---|
1311 | gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
|
---|
1312 | else
|
---|
1313 | gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = FALSE;
|
---|
1314 | gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
|
---|
1315 | wined3d_texture_set_dirty(texture, TRUE);
|
---|
1316 | if (texture->flags & WINED3D_TEXTURE_COND_NP2)
|
---|
1317 | {
|
---|
1318 | gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_CLAMP;
|
---|
1319 | gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_CLAMP;
|
---|
1320 | gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT;
|
---|
1321 | gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT;
|
---|
1322 | gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE;
|
---|
1323 | }
|
---|
1324 |
|
---|
1325 | context = context_acquire(device, NULL);
|
---|
1326 | pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
|
---|
1327 | context_release(context);
|
---|
1328 |
|
---|
1329 | for (i = 0; i < texture->level_count; ++i)
|
---|
1330 | {
|
---|
1331 | struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
|
---|
1332 | surface_setup_location_onopen(surface);
|
---|
1333 | Assert(*shared_handle);
|
---|
1334 | Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture));
|
---|
1335 | }
|
---|
1336 | }
|
---|
1337 |
|
---|
1338 | #ifdef DEBUG
|
---|
1339 | for (i = 0; i < texture->level_count; ++i)
|
---|
1340 | {
|
---|
1341 | Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[i])->texture_name);
|
---|
1342 | }
|
---|
1343 | #endif
|
---|
1344 |
|
---|
1345 | Assert(!device->isInDraw);
|
---|
1346 |
|
---|
1347 | /* flush to ensure the texture is allocated/referenced before it is used/released by another
|
---|
1348 | * process opening/creating it */
|
---|
1349 | Assert(device->context_count == 1);
|
---|
1350 | pVBoxFlushToHost(device->contexts[0]->glCtx);
|
---|
1351 | }
|
---|
1352 | else
|
---|
1353 | {
|
---|
1354 | Assert(!shared_handle);
|
---|
1355 | }
|
---|
1356 | #endif
|
---|
1357 |
|
---|
1358 | return WINED3D_OK;
|
---|
1359 | }
|
---|
1360 |
|
---|
1361 | /* Context activation is done by the caller. */
|
---|
1362 | static HRESULT texture3d_bind(struct wined3d_texture *texture,
|
---|
1363 | struct wined3d_context *context, BOOL srgb)
|
---|
1364 | {
|
---|
1365 | BOOL dummy;
|
---|
1366 |
|
---|
1367 | TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
|
---|
1368 |
|
---|
1369 | return wined3d_texture_bind(texture, context, srgb, &dummy);
|
---|
1370 | }
|
---|
1371 |
|
---|
1372 | /* Do not call while under the GL lock. */
|
---|
1373 | static void texture3d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb)
|
---|
1374 | {
|
---|
1375 | struct wined3d_device *device = texture->resource.device;
|
---|
1376 | struct wined3d_context *context;
|
---|
1377 | BOOL srgb_was_toggled = FALSE;
|
---|
1378 | unsigned int i;
|
---|
1379 |
|
---|
1380 | TRACE("texture %p, srgb %#x.\n", texture, srgb);
|
---|
1381 |
|
---|
1382 | /* TODO: Use already acquired context when possible. */
|
---|
1383 | context = context_acquire(device, NULL);
|
---|
1384 | if (texture->resource.bind_count > 0)
|
---|
1385 | {
|
---|
1386 | BOOL texture_srgb = texture->flags & WINED3D_TEXTURE_IS_SRGB;
|
---|
1387 | BOOL sampler_srgb = texture_srgb_mode(texture, srgb);
|
---|
1388 | srgb_was_toggled = !texture_srgb != !sampler_srgb;
|
---|
1389 |
|
---|
1390 | if (srgb_was_toggled)
|
---|
1391 | {
|
---|
1392 | if (sampler_srgb)
|
---|
1393 | texture->flags |= WINED3D_TEXTURE_IS_SRGB;
|
---|
1394 | else
|
---|
1395 | texture->flags &= ~WINED3D_TEXTURE_IS_SRGB;
|
---|
1396 | }
|
---|
1397 | }
|
---|
1398 |
|
---|
1399 | /* If the texture is marked dirty or the sRGB sampler setting has changed
|
---|
1400 | * since the last load then reload the volumes. */
|
---|
1401 | if (texture->texture_rgb.dirty)
|
---|
1402 | {
|
---|
1403 | for (i = 0; i < texture->level_count; ++i)
|
---|
1404 | {
|
---|
1405 | volume_load(volume_from_resource(texture->sub_resources[i]), context, i,
|
---|
1406 | texture->flags & WINED3D_TEXTURE_IS_SRGB);
|
---|
1407 | }
|
---|
1408 | }
|
---|
1409 | else if (srgb_was_toggled)
|
---|
1410 | {
|
---|
1411 | for (i = 0; i < texture->level_count; ++i)
|
---|
1412 | {
|
---|
1413 | struct wined3d_volume *volume = volume_from_resource(texture->sub_resources[i]);
|
---|
1414 | volume_add_dirty_box(volume, NULL);
|
---|
1415 | volume_load(volume, context, i, texture->flags & WINED3D_TEXTURE_IS_SRGB);
|
---|
1416 | }
|
---|
1417 | }
|
---|
1418 | else
|
---|
1419 | {
|
---|
1420 | TRACE("Texture %p not dirty, nothing to do.\n", texture);
|
---|
1421 | }
|
---|
1422 |
|
---|
1423 | context_release(context);
|
---|
1424 |
|
---|
1425 | /* No longer dirty */
|
---|
1426 | texture->texture_rgb.dirty = FALSE;
|
---|
1427 | }
|
---|
1428 |
|
---|
1429 | static void texture3d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource,
|
---|
1430 | const struct wined3d_box *dirty_region)
|
---|
1431 | {
|
---|
1432 | volume_add_dirty_box(volume_from_resource(sub_resource), dirty_region);
|
---|
1433 | }
|
---|
1434 |
|
---|
1435 | static void texture3d_sub_resource_cleanup(struct wined3d_resource *sub_resource)
|
---|
1436 | {
|
---|
1437 | struct wined3d_volume *volume = volume_from_resource(sub_resource);
|
---|
1438 |
|
---|
1439 | /* Cleanup the container. */
|
---|
1440 | volume_set_container(volume, NULL);
|
---|
1441 | wined3d_volume_decref(volume);
|
---|
1442 | }
|
---|
1443 |
|
---|
1444 | /* Do not call while under the GL lock. */
|
---|
1445 | static void texture3d_unload(struct wined3d_resource *resource)
|
---|
1446 | {
|
---|
1447 | struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
|
---|
1448 | UINT i;
|
---|
1449 |
|
---|
1450 | TRACE("texture %p.\n", texture);
|
---|
1451 |
|
---|
1452 | for (i = 0; i < texture->level_count; ++i)
|
---|
1453 | {
|
---|
1454 | struct wined3d_resource *sub_resource = texture->sub_resources[i];
|
---|
1455 | sub_resource->resource_ops->resource_unload(sub_resource);
|
---|
1456 | }
|
---|
1457 |
|
---|
1458 | wined3d_texture_unload(texture);
|
---|
1459 | }
|
---|
1460 |
|
---|
1461 | static const struct wined3d_texture_ops texture3d_ops =
|
---|
1462 | {
|
---|
1463 | texture3d_bind,
|
---|
1464 | texture3d_preload,
|
---|
1465 | texture3d_sub_resource_add_dirty_region,
|
---|
1466 | texture3d_sub_resource_cleanup,
|
---|
1467 | };
|
---|
1468 |
|
---|
1469 | static const struct wined3d_resource_ops texture3d_resource_ops =
|
---|
1470 | {
|
---|
1471 | texture3d_unload,
|
---|
1472 | };
|
---|
1473 |
|
---|
1474 |
|
---|
1475 | static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
|
---|
1476 | UINT levels, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops
|
---|
1477 | #ifdef VBOX_WITH_WDDM
|
---|
1478 | , HANDLE *shared_handle
|
---|
1479 | , void **pavClientMem
|
---|
1480 | #endif
|
---|
1481 | )
|
---|
1482 | {
|
---|
1483 | const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
---|
1484 | UINT tmp_w, tmp_h, tmp_d;
|
---|
1485 | unsigned int i;
|
---|
1486 | HRESULT hr;
|
---|
1487 |
|
---|
1488 | #ifdef VBOX_WITH_WDDM
|
---|
1489 | if (shared_handle)
|
---|
1490 | {
|
---|
1491 | ERR("shared handle support for volume textures not impemented yet, ignoring!");
|
---|
1492 | }
|
---|
1493 | #endif
|
---|
1494 |
|
---|
1495 | /* TODO: It should only be possible to create textures for formats
|
---|
1496 | * that are reported as supported. */
|
---|
1497 | if (WINED3DFMT_UNKNOWN >= desc->format)
|
---|
1498 | {
|
---|
1499 | WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
|
---|
1500 | return WINED3DERR_INVALIDCALL;
|
---|
1501 | }
|
---|
1502 |
|
---|
1503 | if (!gl_info->supported[EXT_TEXTURE3D])
|
---|
1504 | {
|
---|
1505 | WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture);
|
---|
1506 | return WINED3DERR_INVALIDCALL;
|
---|
1507 | }
|
---|
1508 |
|
---|
1509 | /* Calculate levels for mip mapping. */
|
---|
1510 | if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
|
---|
1511 | {
|
---|
1512 | if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
|
---|
1513 | {
|
---|
1514 | WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n");
|
---|
1515 | return WINED3DERR_INVALIDCALL;
|
---|
1516 | }
|
---|
1517 |
|
---|
1518 | if (levels > 1)
|
---|
1519 | {
|
---|
1520 | WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n");
|
---|
1521 | return WINED3DERR_INVALIDCALL;
|
---|
1522 | }
|
---|
1523 |
|
---|
1524 | levels = 1;
|
---|
1525 | }
|
---|
1526 | else if (!levels)
|
---|
1527 | {
|
---|
1528 | levels = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
|
---|
1529 | TRACE("Calculated levels = %u.\n", levels);
|
---|
1530 | }
|
---|
1531 |
|
---|
1532 | if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
|
---|
1533 | {
|
---|
1534 | UINT pow2_w, pow2_h, pow2_d;
|
---|
1535 | pow2_w = 1;
|
---|
1536 | while (pow2_w < desc->width)
|
---|
1537 | pow2_w <<= 1;
|
---|
1538 | pow2_h = 1;
|
---|
1539 | while (pow2_h < desc->height)
|
---|
1540 | pow2_h <<= 1;
|
---|
1541 | pow2_d = 1;
|
---|
1542 | while (pow2_d < desc->depth)
|
---|
1543 | pow2_d <<= 1;
|
---|
1544 |
|
---|
1545 | if (pow2_w != desc->width || pow2_h != desc->height || pow2_d != desc->depth)
|
---|
1546 | {
|
---|
1547 | if (desc->pool == WINED3D_POOL_SCRATCH)
|
---|
1548 | {
|
---|
1549 | WARN("Creating a scratch NPOT volume texture despite lack of HW support.\n");
|
---|
1550 | }
|
---|
1551 | else
|
---|
1552 | {
|
---|
1553 | WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n",
|
---|
1554 | desc->width, desc->height, desc->depth);
|
---|
1555 | return WINED3DERR_INVALIDCALL;
|
---|
1556 | }
|
---|
1557 | }
|
---|
1558 | }
|
---|
1559 |
|
---|
1560 | #ifdef VBOX_WITH_WDDM
|
---|
1561 | if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
|
---|
1562 | desc, device, parent, parent_ops, &texture3d_resource_ops
|
---|
1563 | , shared_handle, pavClientMem)))
|
---|
1564 | #else
|
---|
1565 | if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
|
---|
1566 | desc, device, parent, parent_ops, &texture3d_resource_ops)))
|
---|
1567 | #endif
|
---|
1568 | {
|
---|
1569 | WARN("Failed to initialize texture, returning %#x.\n", hr);
|
---|
1570 | return hr;
|
---|
1571 | }
|
---|
1572 |
|
---|
1573 | texture->pow2_matrix[0] = 1.0f;
|
---|
1574 | texture->pow2_matrix[5] = 1.0f;
|
---|
1575 | texture->pow2_matrix[10] = 1.0f;
|
---|
1576 | texture->pow2_matrix[15] = 1.0f;
|
---|
1577 | texture->target = GL_TEXTURE_3D;
|
---|
1578 |
|
---|
1579 | /* Generate all the surfaces. */
|
---|
1580 | tmp_w = desc->width;
|
---|
1581 | tmp_h = desc->height;
|
---|
1582 | tmp_d = desc->depth;
|
---|
1583 |
|
---|
1584 | for (i = 0; i < texture->level_count; ++i)
|
---|
1585 | {
|
---|
1586 | struct wined3d_volume *volume;
|
---|
1587 |
|
---|
1588 | /* Create the volume. */
|
---|
1589 | hr = device->device_parent->ops->create_volume(device->device_parent, parent,
|
---|
1590 | tmp_w, tmp_h, tmp_d, desc->format, desc->pool, desc->usage, &volume
|
---|
1591 | #ifdef VBOX_WITH_WDDM
|
---|
1592 | , shared_handle
|
---|
1593 | , pavClientMem
|
---|
1594 | #endif
|
---|
1595 | );
|
---|
1596 | if (FAILED(hr))
|
---|
1597 | {
|
---|
1598 | ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr);
|
---|
1599 | wined3d_texture_cleanup(texture);
|
---|
1600 | return hr;
|
---|
1601 | }
|
---|
1602 |
|
---|
1603 | /* Set its container to this texture. */
|
---|
1604 | volume_set_container(volume, texture);
|
---|
1605 | texture->sub_resources[i] = &volume->resource;
|
---|
1606 |
|
---|
1607 | /* Calculate the next mipmap level. */
|
---|
1608 | tmp_w = max(1, tmp_w >> 1);
|
---|
1609 | tmp_h = max(1, tmp_h >> 1);
|
---|
1610 | tmp_d = max(1, tmp_d >> 1);
|
---|
1611 | }
|
---|
1612 |
|
---|
1613 | return WINED3D_OK;
|
---|
1614 | }
|
---|
1615 |
|
---|
1616 | HRESULT CDECL wined3d_texture_create_2d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
|
---|
1617 | UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
|
---|
1618 | struct wined3d_texture **texture
|
---|
1619 | #ifdef VBOX_WITH_WDDM
|
---|
1620 | , HANDLE *shared_handle
|
---|
1621 | , void **pavClientMem
|
---|
1622 | #endif
|
---|
1623 | )
|
---|
1624 | {
|
---|
1625 | struct wined3d_texture *object;
|
---|
1626 | HRESULT hr;
|
---|
1627 |
|
---|
1628 | TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
|
---|
1629 | device, desc, level_count, surface_flags, parent, parent_ops, texture);
|
---|
1630 |
|
---|
1631 | object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
|
---|
1632 | if (!object)
|
---|
1633 | {
|
---|
1634 | *texture = NULL;
|
---|
1635 | return WINED3DERR_OUTOFVIDEOMEMORY;
|
---|
1636 | }
|
---|
1637 |
|
---|
1638 | #ifdef VBOX_WITH_WDDM
|
---|
1639 | if (FAILED(hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops
|
---|
1640 | , shared_handle, pavClientMem)))
|
---|
1641 | #else
|
---|
1642 | if (FAILED(hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
|
---|
1643 | #endif
|
---|
1644 | {
|
---|
1645 | WARN("Failed to initialize texture, returning %#x.\n", hr);
|
---|
1646 | HeapFree(GetProcessHeap(), 0, object);
|
---|
1647 | *texture = NULL;
|
---|
1648 | return hr;
|
---|
1649 | }
|
---|
1650 |
|
---|
1651 | TRACE("Created texture %p.\n", object);
|
---|
1652 | *texture = object;
|
---|
1653 |
|
---|
1654 | return WINED3D_OK;
|
---|
1655 | }
|
---|
1656 |
|
---|
1657 | HRESULT CDECL wined3d_texture_create_3d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
|
---|
1658 | UINT level_count, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture
|
---|
1659 | #ifdef VBOX_WITH_WDDM
|
---|
1660 | , HANDLE *shared_handle
|
---|
1661 | , void **pavClientMem
|
---|
1662 | #endif
|
---|
1663 | )
|
---|
1664 | {
|
---|
1665 | struct wined3d_texture *object;
|
---|
1666 | HRESULT hr;
|
---|
1667 |
|
---|
1668 | TRACE("device %p, desc %p, level_count %u, parent %p, parent_ops %p, texture %p.\n",
|
---|
1669 | device, desc, level_count, parent, parent_ops, texture);
|
---|
1670 |
|
---|
1671 | object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
|
---|
1672 | if (!object)
|
---|
1673 | {
|
---|
1674 | *texture = NULL;
|
---|
1675 | return WINED3DERR_OUTOFVIDEOMEMORY;
|
---|
1676 | }
|
---|
1677 |
|
---|
1678 | #ifdef VBOX_WITH_WDDM
|
---|
1679 | if (FAILED(hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops
|
---|
1680 | , shared_handle, pavClientMem)))
|
---|
1681 | #else
|
---|
1682 | if (FAILED(hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops)))
|
---|
1683 | #endif
|
---|
1684 | {
|
---|
1685 | WARN("Failed to initialize volumetexture, returning %#x\n", hr);
|
---|
1686 | HeapFree(GetProcessHeap(), 0, object);
|
---|
1687 | *texture = NULL;
|
---|
1688 | return hr;
|
---|
1689 | }
|
---|
1690 |
|
---|
1691 | TRACE("Created texture %p.\n", object);
|
---|
1692 | *texture = object;
|
---|
1693 |
|
---|
1694 | return WINED3D_OK;
|
---|
1695 | }
|
---|
1696 |
|
---|
1697 | HRESULT CDECL wined3d_texture_create_cube(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
|
---|
1698 | UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
|
---|
1699 | struct wined3d_texture **texture
|
---|
1700 | #ifdef VBOX_WITH_WDDM
|
---|
1701 | , HANDLE *shared_handle
|
---|
1702 | , void **pavClientMem
|
---|
1703 | #endif
|
---|
1704 | )
|
---|
1705 | {
|
---|
1706 | struct wined3d_texture *object;
|
---|
1707 | HRESULT hr;
|
---|
1708 |
|
---|
1709 | TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
|
---|
1710 | device, desc, level_count, surface_flags, parent, parent_ops, texture);
|
---|
1711 |
|
---|
1712 | object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
|
---|
1713 | if (!object)
|
---|
1714 | {
|
---|
1715 | *texture = NULL;
|
---|
1716 | return WINED3DERR_OUTOFVIDEOMEMORY;
|
---|
1717 | }
|
---|
1718 |
|
---|
1719 | #ifdef VBOX_WITH_WDDM
|
---|
1720 | if (FAILED(hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops
|
---|
1721 | , shared_handle, pavClientMem)))
|
---|
1722 | #else
|
---|
1723 | if (FAILED(hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
|
---|
1724 | #endif
|
---|
1725 | {
|
---|
1726 | WARN("Failed to initialize cubetexture, returning %#x\n", hr);
|
---|
1727 | HeapFree(GetProcessHeap(), 0, object);
|
---|
1728 | *texture = NULL;
|
---|
1729 | return hr;
|
---|
1730 | }
|
---|
1731 |
|
---|
1732 | TRACE("Created texture %p.\n", object);
|
---|
1733 | *texture = object;
|
---|
1734 |
|
---|
1735 | return WINED3D_OK;
|
---|
1736 | }
|
---|
1737 |
|
---|
1738 | #ifdef VBOX_WITH_WDDM
|
---|
1739 | HRESULT CDECL wined3d_device_blt_voltex(struct wined3d_device *device, struct wined3d_texture *src, struct wined3d_texture *dst,
|
---|
1740 | const struct wined3d_box *pSrcBoxArg, const VBOXPOINT3D *pDstPoin3D)
|
---|
1741 | {
|
---|
1742 | unsigned int level_count, i;
|
---|
1743 | struct wined3d_volume *src_volume;
|
---|
1744 | struct wined3d_volume *dst_volume;
|
---|
1745 | HRESULT hr = S_OK;
|
---|
1746 |
|
---|
1747 | level_count = src->level_count;
|
---|
1748 | if (dst->level_count != level_count)
|
---|
1749 | {
|
---|
1750 | ERR("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
|
---|
1751 | return WINED3DERR_INVALIDCALL;
|
---|
1752 | }
|
---|
1753 |
|
---|
1754 | for (i = 0; i < level_count; ++i)
|
---|
1755 | {
|
---|
1756 | struct wined3d_box SrcBox, *pSrcBox;
|
---|
1757 | VBOXPOINT3D DstPoint, *pDstPoint;
|
---|
1758 |
|
---|
1759 | if (pSrcBoxArg)
|
---|
1760 | {
|
---|
1761 | vboxWddmBoxDivided((VBOXBOX3D*)&SrcBox, (VBOXBOX3D*)pSrcBoxArg, i + 1, true);
|
---|
1762 | pSrcBox = &SrcBox;
|
---|
1763 | }
|
---|
1764 | else
|
---|
1765 | {
|
---|
1766 | pSrcBox = NULL;
|
---|
1767 | }
|
---|
1768 |
|
---|
1769 | if (pDstPoin3D)
|
---|
1770 | {
|
---|
1771 | vboxWddmPoint3DDivided(&DstPoint, pDstPoin3D, i + 1, true);
|
---|
1772 | pDstPoint = &DstPoint;
|
---|
1773 | }
|
---|
1774 | else
|
---|
1775 | {
|
---|
1776 | pDstPoint = NULL;
|
---|
1777 | }
|
---|
1778 |
|
---|
1779 | src_volume = volume_from_resource(src->sub_resources[i]);
|
---|
1780 | dst_volume = volume_from_resource(dst->sub_resources[i]);
|
---|
1781 | hr = wined3d_device_blt_vol(device, src_volume, dst_volume, pSrcBox, pDstPoint);
|
---|
1782 | if (FAILED(hr))
|
---|
1783 | {
|
---|
1784 | ERR("wined3d_device_blt_vol failed, hr %#x.\n", hr);
|
---|
1785 | return hr;
|
---|
1786 | }
|
---|
1787 | }
|
---|
1788 |
|
---|
1789 | return hr;
|
---|
1790 | }
|
---|
1791 | #endif
|
---|