VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/texture.c@ 46579

Last change on this file since 46579 was 46579, checked in by vboxsync, 11 years ago

wine: fix texture cleanup

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette