VirtualBox

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

Last change on this file since 58152 was 52329, checked in by vboxsync, 10 years ago

wddm/crOpenGL: prevent shared objects from being deleted till they can be used

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 64.2 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/*
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
40WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
41
42static 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 */
110static 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
120static 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
143static 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
171void 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. */
178static 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. */
315static 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). */
339void 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
502ULONG 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. */
512ULONG 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
528struct 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
535DWORD CDECL wined3d_texture_set_priority(struct wined3d_texture *texture, DWORD priority)
536{
537 return resource_set_priority(&texture->resource, priority);
538}
539
540DWORD 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. */
546void CDECL wined3d_texture_preload(struct wined3d_texture *texture)
547{
548 texture->texture_ops->texture_preload(texture, SRGB_ANY);
549}
550
551void * 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
558DWORD 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
588DWORD 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
595DWORD 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
602HRESULT 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
618enum 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
625void 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
631struct 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
647HRESULT 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. */
667static 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
730static 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. */
746static 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
787static 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
793static 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. */
807static 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
828static 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
836static const struct wined3d_resource_ops texture2d_resource_ops =
837{
838 texture2d_unload,
839};
840
841static 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 pglChromiumParameteriCR(GL_PIN_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
1015 }
1016 else
1017 {
1018 struct wined3d_context *context = NULL;
1019 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1020 struct gl_texture *gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, FALSE);
1021 texture->texture_rgb.name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
1022 gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
1023 gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
1024 gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
1025 gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
1026 gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
1027 gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
1028 gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
1029 gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
1030 gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
1031 if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
1032 gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
1033 else
1034 gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = FALSE;
1035 gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
1036 wined3d_texture_set_dirty(texture, TRUE);
1037
1038 context = context_acquire(device, NULL);
1039 pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
1040 context_release(context);
1041
1042 for (i = 0; i < texture->level_count; ++i)
1043 {
1044 for (j = 0; j < 6; ++j)
1045 {
1046 UINT idx = j * texture->level_count + i;
1047 struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[idx]);
1048 surface_setup_location_onopen(surface);
1049 Assert(*shared_handle);
1050 Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture));
1051 }
1052 }
1053 }
1054#ifdef DEBUG
1055 for (i = 0; i < texture->level_count; ++i)
1056 {
1057 for (j = 0; j < 6; ++j)
1058 {
1059 UINT idx = j * texture->level_count + i;
1060 Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[idx])->texture_name);
1061 }
1062 }
1063#endif
1064
1065#ifdef DEBUG
1066 for (i = 0; i < texture->level_count; ++i)
1067 {
1068 for (j = 0; j < 6; ++j)
1069 {
1070 UINT idx = j * texture->level_count + i;
1071 Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[idx])->texture_name);
1072 }
1073 }
1074#endif
1075
1076 Assert(!device->isInDraw);
1077
1078 /* flush to ensure the texture is allocated/referenced before it is used/released by another
1079 * process opening/creating it */
1080 Assert(device->context_count == 1);
1081 pVBoxFlushToHost(device->contexts[0]->glCtx);
1082 }
1083 else
1084 {
1085 Assert(!shared_handle);
1086 }
1087#endif
1088
1089 return WINED3D_OK;
1090}
1091
1092static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
1093 UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
1094 const struct wined3d_parent_ops *parent_ops
1095#ifdef VBOX_WITH_WDDM
1096 , HANDLE *shared_handle
1097 , void **pavClientMem
1098#endif
1099 )
1100{
1101 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1102 struct wined3d_resource_desc surface_desc;
1103 UINT pow2_width, pow2_height;
1104 unsigned int i;
1105 HRESULT hr;
1106
1107 /* TODO: It should only be possible to create textures for formats
1108 * that are reported as supported. */
1109 if (WINED3DFMT_UNKNOWN >= desc->format)
1110 {
1111 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
1112 return WINED3DERR_INVALIDCALL;
1113 }
1114
1115 /* Non-power2 support. */
1116 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
1117 {
1118 pow2_width = desc->width;
1119 pow2_height = desc->height;
1120 }
1121 else
1122 {
1123 /* Find the nearest pow2 match. */
1124 pow2_width = pow2_height = 1;
1125 while (pow2_width < desc->width)
1126 pow2_width <<= 1;
1127 while (pow2_height < desc->height)
1128 pow2_height <<= 1;
1129
1130 if (pow2_width != desc->width || pow2_height != desc->height)
1131 {
1132 /* levels == 0 returns an error as well */
1133 if (levels != 1)
1134 {
1135 if (desc->pool == WINED3D_POOL_SCRATCH)
1136 {
1137 WARN("Creating a scratch mipmapped NPOT texture despite lack of HW support.\n");
1138 }
1139 else
1140 {
1141 WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n");
1142 return WINED3DERR_INVALIDCALL;
1143 }
1144 }
1145 }
1146 }
1147
1148 /* Calculate levels for mip mapping. */
1149 if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
1150 {
1151 if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
1152 {
1153 WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n");
1154 return WINED3DERR_INVALIDCALL;
1155 }
1156
1157 if (levels > 1)
1158 {
1159 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n");
1160 return WINED3DERR_INVALIDCALL;
1161 }
1162
1163 levels = 1;
1164 }
1165 else if (!levels)
1166 {
1167 levels = wined3d_log2i(max(desc->width, desc->height)) + 1;
1168 TRACE("Calculated levels = %u.\n", levels);
1169 }
1170
1171#ifdef VBOX_WITH_WDDM
1172 if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
1173 desc, device, parent, parent_ops, &texture2d_resource_ops,
1174 shared_handle, pavClientMem)))
1175#else
1176 if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels,
1177 desc, device, parent, parent_ops, &texture2d_resource_ops)))
1178#endif
1179 {
1180 WARN("Failed to initialize texture, returning %#x.\n", hr);
1181 return hr;
1182 }
1183
1184 /* Precalculated scaling for 'faked' non power of two texture coords.
1185 * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
1186 * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE
1187 * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */
1188 if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]
1189 && (desc->width != pow2_width || desc->height != pow2_height))
1190 {
1191 texture->pow2_matrix[0] = 1.0f;
1192 texture->pow2_matrix[5] = 1.0f;
1193 texture->pow2_matrix[10] = 1.0f;
1194 texture->pow2_matrix[15] = 1.0f;
1195 texture->target = GL_TEXTURE_2D;
1196 texture->flags |= WINED3D_TEXTURE_COND_NP2;
1197 texture->min_mip_lookup = minMipLookup_noFilter;
1198 }
1199 else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (desc->width != pow2_width || desc->height != pow2_height)
1200 && !(desc->format == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE]
1201 && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
1202 {
1203 texture->pow2_matrix[0] = (float)desc->width;
1204 texture->pow2_matrix[5] = (float)desc->height;
1205 texture->pow2_matrix[10] = 1.0f;
1206 texture->pow2_matrix[15] = 1.0f;
1207 texture->target = GL_TEXTURE_RECTANGLE_ARB;
1208 texture->flags |= WINED3D_TEXTURE_COND_NP2;
1209 texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
1210
1211 if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
1212 texture->min_mip_lookup = minMipLookup_noMip;
1213 else
1214 texture->min_mip_lookup = minMipLookup_noFilter;
1215 }
1216 else
1217 {
1218 if ((desc->width != pow2_width) || (desc->height != pow2_height))
1219 {
1220 texture->pow2_matrix[0] = (((float)desc->width) / ((float)pow2_width));
1221 texture->pow2_matrix[5] = (((float)desc->height) / ((float)pow2_height));
1222 texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
1223 }
1224 else
1225 {
1226 texture->pow2_matrix[0] = 1.0f;
1227 texture->pow2_matrix[5] = 1.0f;
1228 }
1229
1230 texture->pow2_matrix[10] = 1.0f;
1231 texture->pow2_matrix[15] = 1.0f;
1232 texture->target = GL_TEXTURE_2D;
1233 }
1234 TRACE("xf(%f) yf(%f)\n", texture->pow2_matrix[0], texture->pow2_matrix[5]);
1235
1236 /* Generate all the surfaces. */
1237 surface_desc = *desc;
1238 surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
1239 for (i = 0; i < texture->level_count; ++i)
1240 {
1241 struct wined3d_surface *surface;
1242
1243 /* Use the callback to create the texture surface. */
1244#ifdef VBOX_WITH_WDDM
1245 if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
1246 parent, &surface_desc, i, surface_flags, &surface
1247 , NULL /* <- we first create a surface in an average "non-shared" fashion and initialize its share properties later (see below)
1248 * this is done this way because the surface does not have its parent (texture) setup properly
1249 * thus we can not initialize texture at this stage */
1250 , pavClientMem ? pavClientMem[i] : NULL
1251 )))
1252#else
1253 if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
1254 parent, &surface_desc, i, surface_flags, &surface)))
1255#endif
1256 {
1257 FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
1258 wined3d_texture_cleanup(texture);
1259 return hr;
1260 }
1261
1262 surface_set_container(surface, texture);
1263 surface_set_texture_target(surface, texture->target, i);
1264 texture->sub_resources[i] = &surface->resource;
1265 TRACE("Created surface level %u @ %p.\n", i, surface);
1266 /* Calculate the next mipmap level. */
1267 surface_desc.width = max(1, surface_desc.width >> 1);
1268 surface_desc.height = max(1, surface_desc.height >> 1);
1269 }
1270
1271#ifdef VBOX_WITH_WDDM
1272 if (VBOXSHRC_IS_SHARED(texture))
1273 {
1274 Assert(shared_handle);
1275 for (i = 0; i < texture->level_count; ++i)
1276 {
1277 VBOXSHRC_COPY_SHAREDATA(surface_from_resource(texture->sub_resources[i]), texture);
1278 }
1279#ifdef DEBUG
1280 for (i = 0; i < texture->level_count; ++i)
1281 {
1282 Assert(!surface_from_resource(texture->sub_resources[i])->texture_name);
1283 }
1284#endif
1285 if (!VBOXSHRC_IS_SHARED_OPENED(texture))
1286 {
1287 for (i = 0; i < texture->level_count; ++i)
1288 {
1289 struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
1290 surface_load_location(surface, SFLAG_INTEXTURE, NULL);
1291 }
1292
1293 Assert(!(*shared_handle));
1294 *shared_handle = VBOXSHRC_GET_SHAREHANDLE(texture);
1295 pglChromiumParameteriCR(GL_PIN_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
1296 }
1297 else
1298 {
1299 struct wined3d_context *context = NULL;
1300 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1301 struct gl_texture *gl_tex = wined3d_texture_get_gl_texture(texture, gl_info, FALSE);
1302 texture->texture_rgb.name = (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture);
1303 gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_WRAP;
1304 gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_WRAP;
1305 gl_tex->states[WINED3DTEXSTA_ADDRESSW] = WINED3D_TADDRESS_WRAP;
1306 gl_tex->states[WINED3DTEXSTA_BORDERCOLOR] = 0;
1307 gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_LINEAR;
1308 gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT; /* GL_NEAREST_MIPMAP_LINEAR */
1309 gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
1310 gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] = 0;
1311 gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
1312 if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
1313 gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
1314 else
1315 gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = FALSE;
1316 gl_tex->states[WINED3DTEXSTA_SHADOW] = FALSE;
1317 wined3d_texture_set_dirty(texture, TRUE);
1318 if (texture->flags & WINED3D_TEXTURE_COND_NP2)
1319 {
1320 gl_tex->states[WINED3DTEXSTA_ADDRESSU] = WINED3D_TADDRESS_CLAMP;
1321 gl_tex->states[WINED3DTEXSTA_ADDRESSV] = WINED3D_TADDRESS_CLAMP;
1322 gl_tex->states[WINED3DTEXSTA_MAGFILTER] = WINED3D_TEXF_POINT;
1323 gl_tex->states[WINED3DTEXSTA_MINFILTER] = WINED3D_TEXF_POINT;
1324 gl_tex->states[WINED3DTEXSTA_MIPFILTER] = WINED3D_TEXF_NONE;
1325 }
1326
1327 context = context_acquire(device, NULL);
1328 pglChromiumParameteriCR(GL_RCUSAGE_TEXTURE_SET_CR, (GLuint)VBOXSHRC_GET_SHAREHANDLE(texture));
1329 context_release(context);
1330
1331 for (i = 0; i < texture->level_count; ++i)
1332 {
1333 struct wined3d_surface *surface = surface_from_resource(texture->sub_resources[i]);
1334 surface_setup_location_onopen(surface);
1335 Assert(*shared_handle);
1336 Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture));
1337 }
1338 }
1339
1340#ifdef DEBUG
1341 for (i = 0; i < texture->level_count; ++i)
1342 {
1343 Assert((GLuint)(*shared_handle) == surface_from_resource(texture->sub_resources[i])->texture_name);
1344 }
1345#endif
1346
1347 Assert(!device->isInDraw);
1348
1349 /* flush to ensure the texture is allocated/referenced before it is used/released by another
1350 * process opening/creating it */
1351 Assert(device->context_count == 1);
1352 pVBoxFlushToHost(device->contexts[0]->glCtx);
1353 }
1354 else
1355 {
1356 Assert(!shared_handle);
1357 }
1358#endif
1359
1360 return WINED3D_OK;
1361}
1362
1363/* Context activation is done by the caller. */
1364static HRESULT texture3d_bind(struct wined3d_texture *texture,
1365 struct wined3d_context *context, BOOL srgb)
1366{
1367 BOOL dummy;
1368
1369 TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb);
1370
1371 return wined3d_texture_bind(texture, context, srgb, &dummy);
1372}
1373
1374/* Do not call while under the GL lock. */
1375static void texture3d_preload(struct wined3d_texture *texture, enum WINED3DSRGB srgb)
1376{
1377 struct wined3d_device *device = texture->resource.device;
1378 struct wined3d_context *context;
1379 BOOL srgb_was_toggled = FALSE;
1380 unsigned int i;
1381
1382 TRACE("texture %p, srgb %#x.\n", texture, srgb);
1383
1384 /* TODO: Use already acquired context when possible. */
1385 context = context_acquire(device, NULL);
1386 if (texture->resource.bind_count > 0)
1387 {
1388 BOOL texture_srgb = texture->flags & WINED3D_TEXTURE_IS_SRGB;
1389 BOOL sampler_srgb = texture_srgb_mode(texture, srgb);
1390 srgb_was_toggled = !texture_srgb != !sampler_srgb;
1391
1392 if (srgb_was_toggled)
1393 {
1394 if (sampler_srgb)
1395 texture->flags |= WINED3D_TEXTURE_IS_SRGB;
1396 else
1397 texture->flags &= ~WINED3D_TEXTURE_IS_SRGB;
1398 }
1399 }
1400
1401 /* If the texture is marked dirty or the sRGB sampler setting has changed
1402 * since the last load then reload the volumes. */
1403 if (texture->texture_rgb.dirty)
1404 {
1405 for (i = 0; i < texture->level_count; ++i)
1406 {
1407 volume_load(volume_from_resource(texture->sub_resources[i]), context, i,
1408 texture->flags & WINED3D_TEXTURE_IS_SRGB);
1409 }
1410 }
1411 else if (srgb_was_toggled)
1412 {
1413 for (i = 0; i < texture->level_count; ++i)
1414 {
1415 struct wined3d_volume *volume = volume_from_resource(texture->sub_resources[i]);
1416 volume_add_dirty_box(volume, NULL);
1417 volume_load(volume, context, i, texture->flags & WINED3D_TEXTURE_IS_SRGB);
1418 }
1419 }
1420 else
1421 {
1422 TRACE("Texture %p not dirty, nothing to do.\n", texture);
1423 }
1424
1425 context_release(context);
1426
1427 /* No longer dirty */
1428 texture->texture_rgb.dirty = FALSE;
1429}
1430
1431static void texture3d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource,
1432 const struct wined3d_box *dirty_region)
1433{
1434 volume_add_dirty_box(volume_from_resource(sub_resource), dirty_region);
1435}
1436
1437static void texture3d_sub_resource_cleanup(struct wined3d_resource *sub_resource)
1438{
1439 struct wined3d_volume *volume = volume_from_resource(sub_resource);
1440
1441 /* Cleanup the container. */
1442 volume_set_container(volume, NULL);
1443 wined3d_volume_decref(volume);
1444}
1445
1446/* Do not call while under the GL lock. */
1447static void texture3d_unload(struct wined3d_resource *resource)
1448{
1449 struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
1450 UINT i;
1451
1452 TRACE("texture %p.\n", texture);
1453
1454 for (i = 0; i < texture->level_count; ++i)
1455 {
1456 struct wined3d_resource *sub_resource = texture->sub_resources[i];
1457 sub_resource->resource_ops->resource_unload(sub_resource);
1458 }
1459
1460 wined3d_texture_unload(texture);
1461}
1462
1463static const struct wined3d_texture_ops texture3d_ops =
1464{
1465 texture3d_bind,
1466 texture3d_preload,
1467 texture3d_sub_resource_add_dirty_region,
1468 texture3d_sub_resource_cleanup,
1469};
1470
1471static const struct wined3d_resource_ops texture3d_resource_ops =
1472{
1473 texture3d_unload,
1474};
1475
1476
1477static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
1478 UINT levels, struct wined3d_device *device, void *parent, const struct wined3d_parent_ops *parent_ops
1479#ifdef VBOX_WITH_WDDM
1480 , HANDLE *shared_handle
1481 , void **pavClientMem
1482#endif
1483 )
1484{
1485 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1486 UINT tmp_w, tmp_h, tmp_d;
1487 unsigned int i;
1488 HRESULT hr;
1489
1490#ifdef VBOX_WITH_WDDM
1491 if (shared_handle)
1492 {
1493 ERR("shared handle support for volume textures not impemented yet, ignoring!");
1494 }
1495#endif
1496
1497 /* TODO: It should only be possible to create textures for formats
1498 * that are reported as supported. */
1499 if (WINED3DFMT_UNKNOWN >= desc->format)
1500 {
1501 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
1502 return WINED3DERR_INVALIDCALL;
1503 }
1504
1505 if (!gl_info->supported[EXT_TEXTURE3D])
1506 {
1507 WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture);
1508 return WINED3DERR_INVALIDCALL;
1509 }
1510
1511 /* Calculate levels for mip mapping. */
1512 if (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP)
1513 {
1514 if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
1515 {
1516 WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n");
1517 return WINED3DERR_INVALIDCALL;
1518 }
1519
1520 if (levels > 1)
1521 {
1522 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n");
1523 return WINED3DERR_INVALIDCALL;
1524 }
1525
1526 levels = 1;
1527 }
1528 else if (!levels)
1529 {
1530 levels = wined3d_log2i(max(max(desc->width, desc->height), desc->depth)) + 1;
1531 TRACE("Calculated levels = %u.\n", levels);
1532 }
1533
1534 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
1535 {
1536 UINT pow2_w, pow2_h, pow2_d;
1537 pow2_w = 1;
1538 while (pow2_w < desc->width)
1539 pow2_w <<= 1;
1540 pow2_h = 1;
1541 while (pow2_h < desc->height)
1542 pow2_h <<= 1;
1543 pow2_d = 1;
1544 while (pow2_d < desc->depth)
1545 pow2_d <<= 1;
1546
1547 if (pow2_w != desc->width || pow2_h != desc->height || pow2_d != desc->depth)
1548 {
1549 if (desc->pool == WINED3D_POOL_SCRATCH)
1550 {
1551 WARN("Creating a scratch NPOT volume texture despite lack of HW support.\n");
1552 }
1553 else
1554 {
1555 WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n",
1556 desc->width, desc->height, desc->depth);
1557 return WINED3DERR_INVALIDCALL;
1558 }
1559 }
1560 }
1561
1562#ifdef VBOX_WITH_WDDM
1563 if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
1564 desc, device, parent, parent_ops, &texture3d_resource_ops
1565 , shared_handle, pavClientMem)))
1566#else
1567 if (FAILED(hr = wined3d_texture_init(texture, &texture3d_ops, 1, levels,
1568 desc, device, parent, parent_ops, &texture3d_resource_ops)))
1569#endif
1570 {
1571 WARN("Failed to initialize texture, returning %#x.\n", hr);
1572 return hr;
1573 }
1574
1575 texture->pow2_matrix[0] = 1.0f;
1576 texture->pow2_matrix[5] = 1.0f;
1577 texture->pow2_matrix[10] = 1.0f;
1578 texture->pow2_matrix[15] = 1.0f;
1579 texture->target = GL_TEXTURE_3D;
1580
1581 /* Generate all the surfaces. */
1582 tmp_w = desc->width;
1583 tmp_h = desc->height;
1584 tmp_d = desc->depth;
1585
1586 for (i = 0; i < texture->level_count; ++i)
1587 {
1588 struct wined3d_volume *volume;
1589
1590 /* Create the volume. */
1591 hr = device->device_parent->ops->create_volume(device->device_parent, parent,
1592 tmp_w, tmp_h, tmp_d, desc->format, desc->pool, desc->usage, &volume
1593#ifdef VBOX_WITH_WDDM
1594 , shared_handle
1595 , pavClientMem ? pavClientMem[i] : NULL
1596#endif
1597 );
1598 if (FAILED(hr))
1599 {
1600 ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr);
1601 wined3d_texture_cleanup(texture);
1602 return hr;
1603 }
1604
1605 /* Set its container to this texture. */
1606 volume_set_container(volume, texture);
1607 texture->sub_resources[i] = &volume->resource;
1608
1609 /* Calculate the next mipmap level. */
1610 tmp_w = max(1, tmp_w >> 1);
1611 tmp_h = max(1, tmp_h >> 1);
1612 tmp_d = max(1, tmp_d >> 1);
1613 }
1614
1615 return WINED3D_OK;
1616}
1617
1618HRESULT CDECL wined3d_texture_create_2d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
1619 UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
1620 struct wined3d_texture **texture
1621#ifdef VBOX_WITH_WDDM
1622 , HANDLE *shared_handle
1623 , void **pavClientMem
1624#endif
1625 )
1626{
1627 struct wined3d_texture *object;
1628 HRESULT hr;
1629
1630 TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
1631 device, desc, level_count, surface_flags, parent, parent_ops, texture);
1632
1633 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1634 if (!object)
1635 {
1636 *texture = NULL;
1637 return WINED3DERR_OUTOFVIDEOMEMORY;
1638 }
1639
1640#ifdef VBOX_WITH_WDDM
1641 if (FAILED(hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops
1642 , shared_handle, pavClientMem)))
1643#else
1644 if (FAILED(hr = texture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
1645#endif
1646 {
1647 WARN("Failed to initialize texture, returning %#x.\n", hr);
1648 HeapFree(GetProcessHeap(), 0, object);
1649 *texture = NULL;
1650 return hr;
1651 }
1652
1653 TRACE("Created texture %p.\n", object);
1654 *texture = object;
1655
1656 return WINED3D_OK;
1657}
1658
1659HRESULT CDECL wined3d_texture_create_3d(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
1660 UINT level_count, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture
1661#ifdef VBOX_WITH_WDDM
1662 , HANDLE *shared_handle
1663 , void **pavClientMem
1664#endif
1665 )
1666{
1667 struct wined3d_texture *object;
1668 HRESULT hr;
1669
1670 TRACE("device %p, desc %p, level_count %u, parent %p, parent_ops %p, texture %p.\n",
1671 device, desc, level_count, parent, parent_ops, texture);
1672
1673 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1674 if (!object)
1675 {
1676 *texture = NULL;
1677 return WINED3DERR_OUTOFVIDEOMEMORY;
1678 }
1679
1680#ifdef VBOX_WITH_WDDM
1681 if (FAILED(hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops
1682 , shared_handle, pavClientMem)))
1683#else
1684 if (FAILED(hr = volumetexture_init(object, desc, level_count, device, parent, parent_ops)))
1685#endif
1686 {
1687 WARN("Failed to initialize volumetexture, returning %#x\n", hr);
1688 HeapFree(GetProcessHeap(), 0, object);
1689 *texture = NULL;
1690 return hr;
1691 }
1692
1693 TRACE("Created texture %p.\n", object);
1694 *texture = object;
1695
1696 return WINED3D_OK;
1697}
1698
1699HRESULT CDECL wined3d_texture_create_cube(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
1700 UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
1701 struct wined3d_texture **texture
1702#ifdef VBOX_WITH_WDDM
1703 , HANDLE *shared_handle
1704 , void **pavClientMem
1705#endif
1706 )
1707{
1708 struct wined3d_texture *object;
1709 HRESULT hr;
1710
1711 TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
1712 device, desc, level_count, surface_flags, parent, parent_ops, texture);
1713
1714 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1715 if (!object)
1716 {
1717 *texture = NULL;
1718 return WINED3DERR_OUTOFVIDEOMEMORY;
1719 }
1720
1721#ifdef VBOX_WITH_WDDM
1722 if (FAILED(hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops
1723 , shared_handle, pavClientMem)))
1724#else
1725 if (FAILED(hr = cubetexture_init(object, desc, level_count, surface_flags, device, parent, parent_ops)))
1726#endif
1727 {
1728 WARN("Failed to initialize cubetexture, returning %#x\n", hr);
1729 HeapFree(GetProcessHeap(), 0, object);
1730 *texture = NULL;
1731 return hr;
1732 }
1733
1734 TRACE("Created texture %p.\n", object);
1735 *texture = object;
1736
1737 return WINED3D_OK;
1738}
1739
1740#ifdef VBOX_WITH_WDDM
1741HRESULT CDECL wined3d_device_blt_voltex(struct wined3d_device *device, struct wined3d_texture *src, struct wined3d_texture *dst,
1742 const struct wined3d_box *pSrcBoxArg, const VBOXPOINT3D *pDstPoin3D)
1743{
1744 unsigned int level_count, i;
1745 struct wined3d_volume *src_volume;
1746 struct wined3d_volume *dst_volume;
1747 HRESULT hr = S_OK;
1748
1749 level_count = src->level_count;
1750 if (dst->level_count != level_count)
1751 {
1752 ERR("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
1753 return WINED3DERR_INVALIDCALL;
1754 }
1755
1756 for (i = 0; i < level_count; ++i)
1757 {
1758 struct wined3d_box SrcBox, *pSrcBox;
1759 VBOXPOINT3D DstPoint, *pDstPoint;
1760
1761 if (pSrcBoxArg)
1762 {
1763 vboxWddmBoxDivided((VBOXBOX3D*)&SrcBox, (VBOXBOX3D*)pSrcBoxArg, i + 1, true);
1764 pSrcBox = &SrcBox;
1765 }
1766 else
1767 {
1768 pSrcBox = NULL;
1769 }
1770
1771 if (pDstPoin3D)
1772 {
1773 vboxWddmPoint3DDivided(&DstPoint, pDstPoin3D, i + 1, true);
1774 pDstPoint = &DstPoint;
1775 }
1776 else
1777 {
1778 pDstPoint = NULL;
1779 }
1780
1781 src_volume = volume_from_resource(src->sub_resources[i]);
1782 dst_volume = volume_from_resource(dst->sub_resources[i]);
1783 hr = wined3d_device_blt_vol(device, src_volume, dst_volume, pSrcBox, pDstPoint);
1784 if (FAILED(hr))
1785 {
1786 ERR("wined3d_device_blt_vol failed, hr %#x.\n", hr);
1787 return hr;
1788 }
1789 }
1790
1791 return hr;
1792}
1793#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