VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/texture.c@ 19678

Last change on this file since 19678 was 19678, checked in by vboxsync, 16 years ago

opengl: update wine to 1.1.21, add d3d9.dll to build list

  • Property svn:eol-style set to native
File size: 17.6 KB
Line 
1/*
2 * IWineD3DTexture implementation
3 *
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2002-2005 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24/*
25 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
26 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
27 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
28 * a choice of LGPL license versions is made available with the language indicating
29 * that LGPLv2 or any later version may be used, or where a choice of which version
30 * of the LGPL is applied is otherwise unspecified.
31 */
32
33#include "config.h"
34#include "wined3d_private.h"
35
36WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
37#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
38
39/* *******************************************
40 IWineD3DTexture IUnknown parts follow
41 ******************************************* */
42static HRESULT WINAPI IWineD3DTextureImpl_QueryInterface(IWineD3DTexture *iface, REFIID riid, LPVOID *ppobj)
43{
44 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
45 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
46 if (IsEqualGUID(riid, &IID_IUnknown)
47 || IsEqualGUID(riid, &IID_IWineD3DBase)
48 || IsEqualGUID(riid, &IID_IWineD3DResource)
49 || IsEqualGUID(riid, &IID_IWineD3DBaseTexture)
50 || IsEqualGUID(riid, &IID_IWineD3DTexture)){
51 IUnknown_AddRef(iface);
52 *ppobj = This;
53 return WINED3D_OK;
54 }
55 *ppobj = NULL;
56 return E_NOINTERFACE;
57}
58
59static ULONG WINAPI IWineD3DTextureImpl_AddRef(IWineD3DTexture *iface) {
60 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
61 TRACE("(%p) : AddRef increasing from %d\n", This, This->resource.ref);
62 return InterlockedIncrement(&This->resource.ref);
63}
64
65static ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
66 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
67 ULONG ref;
68 TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
69 ref = InterlockedDecrement(&This->resource.ref);
70 if (ref == 0) {
71 IWineD3DTexture_Destroy(iface, D3DCB_DefaultDestroySurface);
72 }
73 return ref;
74}
75
76
77/* ****************************************************
78 IWineD3DTexture IWineD3DResource parts follow
79 **************************************************** */
80static HRESULT WINAPI IWineD3DTextureImpl_GetDevice(IWineD3DTexture *iface, IWineD3DDevice** ppDevice) {
81 return resource_get_device((IWineD3DResource *)iface, ppDevice);
82}
83
84static HRESULT WINAPI IWineD3DTextureImpl_SetPrivateData(IWineD3DTexture *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
85 return resource_set_private_data((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
86}
87
88static HRESULT WINAPI IWineD3DTextureImpl_GetPrivateData(IWineD3DTexture *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
89 return resource_get_private_data((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
90}
91
92static HRESULT WINAPI IWineD3DTextureImpl_FreePrivateData(IWineD3DTexture *iface, REFGUID refguid) {
93 return resource_free_private_data((IWineD3DResource *)iface, refguid);
94}
95
96static DWORD WINAPI IWineD3DTextureImpl_SetPriority(IWineD3DTexture *iface, DWORD PriorityNew) {
97 return resource_set_priority((IWineD3DResource *)iface, PriorityNew);
98}
99
100static DWORD WINAPI IWineD3DTextureImpl_GetPriority(IWineD3DTexture *iface) {
101 return resource_get_priority((IWineD3DResource *)iface);
102}
103
104void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) {
105
106 /* Override the IWineD3DResource PreLoad method */
107 unsigned int i;
108 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
109 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
110 BOOL srgb_mode;
111 BOOL *dirty;
112
113 TRACE("(%p) : About to load texture\n", This);
114
115 switch(srgb) {
116 case SRGB_RGB: srgb_mode = FALSE; break;
117 case SRGB_BOTH: texture_internal_preload(iface, SRGB_RGB);
118 case SRGB_SRGB: srgb_mode = TRUE; break;
119 /* DONTKNOW, and shut up the compiler */
120 default: srgb_mode = This->baseTexture.is_srgb; break;
121 }
122 dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty;
123
124 if(!device->isInDraw) {
125 /* ActivateContext sets isInDraw to TRUE when loading a pbuffer into a texture, thus no danger of
126 * recursive calls
127 */
128 ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
129 }
130
131 if (This->resource.format_desc->format == WINED3DFMT_P8
132 || This->resource.format_desc->format == WINED3DFMT_A8P8)
133 {
134 for (i = 0; i < This->baseTexture.levels; i++) {
135 if(palette9_changed((IWineD3DSurfaceImpl *)This->surfaces[i])) {
136 TRACE("Reloading surface because the d3d8/9 palette was changed\n");
137 /* TODO: This is not necessarily needed with hw palettized texture support */
138 IWineD3DSurface_LoadLocation(This->surfaces[i], SFLAG_INSYSMEM, NULL);
139 /* Make sure the texture is reloaded because of the palette change, this kills performance though :( */
140 IWineD3DSurface_ModifyLocation(This->surfaces[i], SFLAG_INTEXTURE, FALSE);
141 }
142 }
143 }
144 /* If the texture is marked dirty or the srgb sampler setting has changed since the last load then reload the surfaces */
145 if (*dirty) {
146 for (i = 0; i < This->baseTexture.levels; i++) {
147 IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode);
148 }
149 } else {
150 TRACE("(%p) Texture not dirty, nothing to do\n" , iface);
151 }
152
153 /* No longer dirty */
154 *dirty = FALSE;
155
156 return ;
157}
158
159static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) {
160 texture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY);
161}
162
163static void WINAPI IWineD3DTextureImpl_UnLoad(IWineD3DTexture *iface) {
164 unsigned int i;
165 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
166 TRACE("(%p)\n", This);
167
168 /* Unload all the surfaces and reset the texture name. If UnLoad was called on the
169 * surface before, this one will be a NOP and vice versa. Unloading an unloaded
170 * surface is fine
171 */
172 for (i = 0; i < This->baseTexture.levels; i++) {
173 IWineD3DSurface_UnLoad(This->surfaces[i]);
174 surface_set_texture_name(This->surfaces[i], 0, FALSE); /* Delete rgb name */
175 surface_set_texture_name(This->surfaces[i], 0, TRUE); /* delete srgb name */
176 }
177
178 basetexture_unload((IWineD3DBaseTexture *)iface);
179}
180
181static WINED3DRESOURCETYPE WINAPI IWineD3DTextureImpl_GetType(IWineD3DTexture *iface) {
182 return resource_get_type((IWineD3DResource *)iface);
183}
184
185static HRESULT WINAPI IWineD3DTextureImpl_GetParent(IWineD3DTexture *iface, IUnknown **pParent) {
186 return resource_get_parent((IWineD3DResource *)iface, pParent);
187}
188
189/* ******************************************************
190 IWineD3DTexture IWineD3DBaseTexture parts follow
191 ****************************************************** */
192static DWORD WINAPI IWineD3DTextureImpl_SetLOD(IWineD3DTexture *iface, DWORD LODNew) {
193 return basetexture_set_lod((IWineD3DBaseTexture *)iface, LODNew);
194}
195
196static DWORD WINAPI IWineD3DTextureImpl_GetLOD(IWineD3DTexture *iface) {
197 return basetexture_get_lod((IWineD3DBaseTexture *)iface);
198}
199
200static DWORD WINAPI IWineD3DTextureImpl_GetLevelCount(IWineD3DTexture *iface) {
201 return basetexture_get_level_count((IWineD3DBaseTexture *)iface);
202}
203
204static HRESULT WINAPI IWineD3DTextureImpl_SetAutoGenFilterType(IWineD3DTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType) {
205 return basetexture_set_autogen_filter_type((IWineD3DBaseTexture *)iface, FilterType);
206}
207
208static WINED3DTEXTUREFILTERTYPE WINAPI IWineD3DTextureImpl_GetAutoGenFilterType(IWineD3DTexture *iface) {
209 return basetexture_get_autogen_filter_type((IWineD3DBaseTexture *)iface);
210}
211
212static void WINAPI IWineD3DTextureImpl_GenerateMipSubLevels(IWineD3DTexture *iface) {
213 basetexture_generate_mipmaps((IWineD3DBaseTexture *)iface);
214}
215
216/* Internal function, No d3d mapping */
217static BOOL WINAPI IWineD3DTextureImpl_SetDirty(IWineD3DTexture *iface, BOOL dirty) {
218 return basetexture_set_dirty((IWineD3DBaseTexture *)iface, dirty);
219}
220
221static BOOL WINAPI IWineD3DTextureImpl_GetDirty(IWineD3DTexture *iface) {
222 return basetexture_get_dirty((IWineD3DBaseTexture *)iface);
223}
224
225static HRESULT WINAPI IWineD3DTextureImpl_BindTexture(IWineD3DTexture *iface, BOOL srgb) {
226 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
227 BOOL set_gl_texture_desc;
228 HRESULT hr;
229
230 TRACE("(%p) : relay to BaseTexture\n", This);
231
232 hr = basetexture_bind((IWineD3DBaseTexture *)iface, srgb, &set_gl_texture_desc);
233 if (set_gl_texture_desc && SUCCEEDED(hr)) {
234 UINT i;
235 for (i = 0; i < This->baseTexture.levels; ++i) {
236 if(This->baseTexture.is_srgb) {
237 surface_set_texture_name(This->surfaces[i], This->baseTexture.srgbTextureName, TRUE);
238 } else {
239 surface_set_texture_name(This->surfaces[i], This->baseTexture.textureName, FALSE);
240 }
241 }
242 /* Conditinal non power of two textures use a different clamping default. If we're using the GL_WINE_normalized_texrect
243 * partial driver emulation, we're dealing with a GL_TEXTURE_2D texture which has the address mode set to repeat - something
244 * that prevents us from hitting the accelerated codepath. Thus manually set the GL state. The same applies to filtering.
245 * Even if the texture has only one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW fallback on macos.
246 */
247 if(IWineD3DBaseTexture_IsCondNP2(iface)) {
248 ENTER_GL();
249 glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
250 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)");
251 glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
252 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)");
253 glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
254 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MIN_FILTER, GL_NEAREST)");
255 glTexParameteri(IWineD3DTexture_GetTextureDimensions(iface), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
256 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MAG_FILTER, GL_NEAREST)");
257 LEAVE_GL();
258 This->baseTexture.states[WINED3DTEXSTA_ADDRESSU] = WINED3DTADDRESS_CLAMP;
259 This->baseTexture.states[WINED3DTEXSTA_ADDRESSV] = WINED3DTADDRESS_CLAMP;
260 This->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
261 This->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
262 This->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE;
263 }
264 }
265
266 return hr;
267}
268
269static UINT WINAPI IWineD3DTextureImpl_GetTextureDimensions(IWineD3DTexture *iface) {
270 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
271 TRACE("(%p)\n", This);
272
273 return This->target;
274}
275
276static BOOL WINAPI IWineD3DTextureImpl_IsCondNP2(IWineD3DTexture *iface) {
277 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
278 TRACE("(%p)\n", This);
279
280 return This->cond_np2;
281}
282
283static void WINAPI IWineD3DTextureImpl_ApplyStateChanges(IWineD3DTexture *iface,
284 const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
285 const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
286 TRACE("(%p) : relay to BaseTexture\n", iface);
287 basetexture_apply_state_changes((IWineD3DBaseTexture *)iface, textureStates, samplerStates);
288}
289
290/* *******************************************
291 IWineD3DTexture IWineD3DTexture parts follow
292 ******************************************* */
293static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) {
294 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
295 unsigned int i;
296
297 TRACE("(%p) : Cleaning up\n",This);
298 for (i = 0; i < This->baseTexture.levels; i++) {
299 if (This->surfaces[i] != NULL) {
300 /* Clean out the texture name we gave to the surface so that the surface doesn't try and release it */
301 surface_set_texture_name(This->surfaces[i], 0, TRUE);
302 surface_set_texture_name(This->surfaces[i], 0, FALSE);
303 surface_set_texture_target(This->surfaces[i], 0);
304 IWineD3DSurface_SetContainer(This->surfaces[i], 0);
305 D3DCB_DestroySurface(This->surfaces[i]);
306 }
307 }
308 TRACE("(%p) : cleaning up base texture\n", This);
309 basetexture_cleanup((IWineD3DBaseTexture *)iface);
310 /* free the object */
311 HeapFree(GetProcessHeap(), 0, This);
312}
313
314static HRESULT WINAPI IWineD3DTextureImpl_GetLevelDesc(IWineD3DTexture *iface, UINT Level, WINED3DSURFACE_DESC* pDesc) {
315 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
316
317 if (Level < This->baseTexture.levels) {
318 TRACE("(%p) Level (%d)\n", This, Level);
319 return IWineD3DSurface_GetDesc(This->surfaces[Level], pDesc);
320 }
321 WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
322 return WINED3DERR_INVALIDCALL;
323}
324
325static HRESULT WINAPI IWineD3DTextureImpl_GetSurfaceLevel(IWineD3DTexture *iface, UINT Level, IWineD3DSurface** ppSurfaceLevel) {
326 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
327 HRESULT hr = WINED3DERR_INVALIDCALL;
328
329 if (Level < This->baseTexture.levels) {
330 *ppSurfaceLevel = This->surfaces[Level];
331 IWineD3DSurface_AddRef(This->surfaces[Level]);
332 hr = WINED3D_OK;
333 TRACE("(%p) : returning %p for level %d\n", This, *ppSurfaceLevel, Level);
334 }
335 if (WINED3D_OK != hr) {
336 WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
337 *ppSurfaceLevel = NULL; /* Just to be on the safe side.. */
338 }
339 return hr;
340}
341
342static HRESULT WINAPI IWineD3DTextureImpl_LockRect(IWineD3DTexture *iface, UINT Level, WINED3DLOCKED_RECT *pLockedRect,
343 CONST RECT *pRect, DWORD Flags) {
344 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
345 HRESULT hr = WINED3DERR_INVALIDCALL;
346
347 if (Level < This->baseTexture.levels) {
348 hr = IWineD3DSurface_LockRect(This->surfaces[Level], pLockedRect, pRect, Flags);
349 }
350 if (WINED3D_OK == hr) {
351 TRACE("(%p) Level (%d) success\n", This, Level);
352 } else {
353 WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
354 }
355
356 return hr;
357}
358
359static HRESULT WINAPI IWineD3DTextureImpl_UnlockRect(IWineD3DTexture *iface, UINT Level) {
360 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
361 HRESULT hr = WINED3DERR_INVALIDCALL;
362
363 if (Level < This->baseTexture.levels) {
364 hr = IWineD3DSurface_UnlockRect(This->surfaces[Level]);
365 }
366 if ( WINED3D_OK == hr) {
367 TRACE("(%p) Level (%d) success\n", This, Level);
368 } else {
369 WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
370 }
371 return hr;
372}
373
374static HRESULT WINAPI IWineD3DTextureImpl_AddDirtyRect(IWineD3DTexture *iface, CONST RECT* pDirtyRect) {
375 IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
376 This->baseTexture.dirty = TRUE;
377 This->baseTexture.srgbDirty = TRUE;
378 TRACE("(%p) : dirtyfication of surface Level (0)\n", This);
379 surface_add_dirty_rect(This->surfaces[0], pDirtyRect);
380
381 return WINED3D_OK;
382}
383
384const IWineD3DTextureVtbl IWineD3DTexture_Vtbl =
385{
386 /* IUnknown */
387 IWineD3DTextureImpl_QueryInterface,
388 IWineD3DTextureImpl_AddRef,
389 IWineD3DTextureImpl_Release,
390 /* IWineD3DResource */
391 IWineD3DTextureImpl_GetParent,
392 IWineD3DTextureImpl_GetDevice,
393 IWineD3DTextureImpl_SetPrivateData,
394 IWineD3DTextureImpl_GetPrivateData,
395 IWineD3DTextureImpl_FreePrivateData,
396 IWineD3DTextureImpl_SetPriority,
397 IWineD3DTextureImpl_GetPriority,
398 IWineD3DTextureImpl_PreLoad,
399 IWineD3DTextureImpl_UnLoad,
400 IWineD3DTextureImpl_GetType,
401 /* IWineD3DBaseTexture */
402 IWineD3DTextureImpl_SetLOD,
403 IWineD3DTextureImpl_GetLOD,
404 IWineD3DTextureImpl_GetLevelCount,
405 IWineD3DTextureImpl_SetAutoGenFilterType,
406 IWineD3DTextureImpl_GetAutoGenFilterType,
407 IWineD3DTextureImpl_GenerateMipSubLevels,
408 IWineD3DTextureImpl_SetDirty,
409 IWineD3DTextureImpl_GetDirty,
410 IWineD3DTextureImpl_BindTexture,
411 IWineD3DTextureImpl_GetTextureDimensions,
412 IWineD3DTextureImpl_IsCondNP2,
413 IWineD3DTextureImpl_ApplyStateChanges,
414 /* IWineD3DTexture */
415 IWineD3DTextureImpl_Destroy,
416 IWineD3DTextureImpl_GetLevelDesc,
417 IWineD3DTextureImpl_GetSurfaceLevel,
418 IWineD3DTextureImpl_LockRect,
419 IWineD3DTextureImpl_UnlockRect,
420 IWineD3DTextureImpl_AddDirtyRect
421};
Note: See TracBrowser for help on using the repository browser.

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