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