VirtualBox

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

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

header fixes

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