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