VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/volume.c@ 23571

Last change on this file since 23571 was 23571, checked in by vboxsync, 15 years ago

crOpenGL: update to wine 1.1.30

  • Property svn:eol-style set to native
File size: 16.4 KB
Line 
1/*
2 * IWineD3DVolume implementation
3 *
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2002-2005 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2009 Henri Verbeet 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_surface);
37#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
38
39/* Context activation is done by the caller. */
40static void volume_bind_and_dirtify(IWineD3DVolume *iface) {
41 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
42 IWineD3DVolumeTexture *texture;
43 DWORD active_sampler;
44
45 /* We don't need a specific texture unit, but after binding the texture the current unit is dirty.
46 * Read the unit back instead of switching to 0, this avoids messing around with the state manager's
47 * gl states. The current texture unit should always be a valid one.
48 *
49 * To be more specific, this is tricky because we can implicitly be called
50 * from sampler() in state.c. This means we can't touch anything other than
51 * whatever happens to be the currently active texture, or we would risk
52 * marking already applied sampler states dirty again.
53 *
54 * TODO: Track the current active texture per GL context instead of using glGet
55 */
56 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
57 GLint active_texture;
58 ENTER_GL();
59 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
60 LEAVE_GL();
61 active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB];
62 } else {
63 active_sampler = 0;
64 }
65
66 if (active_sampler != WINED3D_UNMAPPED_STAGE)
67 {
68 IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler));
69 }
70
71 if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DVolumeTexture, (void **)&texture))) {
72 IWineD3DVolumeTexture_BindTexture(texture, FALSE);
73 IWineD3DVolumeTexture_Release(texture);
74 } else {
75 ERR("Volume should be part of a volume texture\n");
76 }
77}
78
79void volume_add_dirty_box(IWineD3DVolume *iface, const WINED3DBOX *dirty_box)
80{
81 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
82
83 This->dirty = TRUE;
84 if (dirty_box)
85 {
86 This->lockedBox.Left = min(This->lockedBox.Left, dirty_box->Left);
87 This->lockedBox.Top = min(This->lockedBox.Top, dirty_box->Top);
88 This->lockedBox.Front = min(This->lockedBox.Front, dirty_box->Front);
89 This->lockedBox.Right = max(This->lockedBox.Right, dirty_box->Right);
90 This->lockedBox.Bottom = max(This->lockedBox.Bottom, dirty_box->Bottom);
91 This->lockedBox.Back = max(This->lockedBox.Back, dirty_box->Back);
92 }
93 else
94 {
95 This->lockedBox.Left = 0;
96 This->lockedBox.Top = 0;
97 This->lockedBox.Front = 0;
98 This->lockedBox.Right = This->currentDesc.Width;
99 This->lockedBox.Bottom = This->currentDesc.Height;
100 This->lockedBox.Back = This->currentDesc.Depth;
101 }
102}
103
104/* *******************************************
105 IWineD3DVolume IUnknown parts follow
106 ******************************************* */
107static HRESULT WINAPI IWineD3DVolumeImpl_QueryInterface(IWineD3DVolume *iface, REFIID riid, LPVOID *ppobj)
108{
109 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
110 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
111 if (IsEqualGUID(riid, &IID_IUnknown)
112 || IsEqualGUID(riid, &IID_IWineD3DBase)
113 || IsEqualGUID(riid, &IID_IWineD3DVolume)){
114 IUnknown_AddRef(iface);
115 *ppobj = This;
116 return S_OK;
117 }
118 *ppobj = NULL;
119 return E_NOINTERFACE;
120}
121
122static ULONG WINAPI IWineD3DVolumeImpl_AddRef(IWineD3DVolume *iface) {
123 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
124 TRACE("(%p) : AddRef increasing from %d\n", This, This->resource.ref);
125 return InterlockedIncrement(&This->resource.ref);
126}
127
128static ULONG WINAPI IWineD3DVolumeImpl_Release(IWineD3DVolume *iface) {
129 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
130 ULONG ref;
131 TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
132 ref = InterlockedDecrement(&This->resource.ref);
133 if (ref == 0) {
134 resource_cleanup((IWineD3DResource *)iface);
135 This->resource.parent_ops->wined3d_object_destroyed(This->resource.parent);
136 HeapFree(GetProcessHeap(), 0, This);
137 }
138 return ref;
139}
140
141/* ****************************************************
142 IWineD3DVolume IWineD3DResource parts follow
143 **************************************************** */
144static HRESULT WINAPI IWineD3DVolumeImpl_GetParent(IWineD3DVolume *iface, IUnknown **pParent) {
145 return resource_get_parent((IWineD3DResource *)iface, pParent);
146}
147
148static HRESULT WINAPI IWineD3DVolumeImpl_GetDevice(IWineD3DVolume *iface, IWineD3DDevice** ppDevice) {
149 return resource_get_device((IWineD3DResource *)iface, ppDevice);
150}
151
152static HRESULT WINAPI IWineD3DVolumeImpl_SetPrivateData(IWineD3DVolume *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
153 return resource_set_private_data((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
154}
155
156static HRESULT WINAPI IWineD3DVolumeImpl_GetPrivateData(IWineD3DVolume *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
157 return resource_get_private_data((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
158}
159
160static HRESULT WINAPI IWineD3DVolumeImpl_FreePrivateData(IWineD3DVolume *iface, REFGUID refguid) {
161 return resource_free_private_data((IWineD3DResource *)iface, refguid);
162}
163
164static DWORD WINAPI IWineD3DVolumeImpl_SetPriority(IWineD3DVolume *iface, DWORD PriorityNew) {
165 return resource_set_priority((IWineD3DResource *)iface, PriorityNew);
166}
167
168static DWORD WINAPI IWineD3DVolumeImpl_GetPriority(IWineD3DVolume *iface) {
169 return resource_get_priority((IWineD3DResource *)iface);
170}
171
172static void WINAPI IWineD3DVolumeImpl_PreLoad(IWineD3DVolume *iface) {
173 FIXME("iface %p stub!\n", iface);
174}
175
176static void WINAPI IWineD3DVolumeImpl_UnLoad(IWineD3DVolume *iface) {
177 /* The whole content is shadowed on This->resource.allocatedMemory, and the
178 * texture name is managed by the VolumeTexture container
179 */
180 TRACE("(%p): Nothing to do\n", iface);
181}
182
183static WINED3DRESOURCETYPE WINAPI IWineD3DVolumeImpl_GetType(IWineD3DVolume *iface) {
184 return resource_get_type((IWineD3DResource *)iface);
185}
186
187/* *******************************************
188 IWineD3DVolume parts follow
189 ******************************************* */
190static HRESULT WINAPI IWineD3DVolumeImpl_GetContainer(IWineD3DVolume *iface, REFIID riid, void** ppContainer) {
191 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
192
193 TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
194
195 if (!ppContainer) {
196 ERR("Called without a valid ppContainer.\n");
197 }
198
199 /* Although surfaces can be standalone, volumes can't */
200 if (!This->container) {
201 ERR("Volume without an container. Should not happen.\n");
202 }
203
204 TRACE("Relaying to QueryInterface\n");
205 return IUnknown_QueryInterface(This->container, riid, ppContainer);
206}
207
208static HRESULT WINAPI IWineD3DVolumeImpl_GetDesc(IWineD3DVolume *iface, WINED3DVOLUME_DESC* pDesc) {
209 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
210 TRACE("(%p) : copying into %p\n", This, pDesc);
211
212 pDesc->Format = This->resource.format_desc->format;
213 pDesc->Type = This->resource.resourceType;
214 pDesc->Usage = This->resource.usage;
215 pDesc->Pool = This->resource.pool;
216 pDesc->Size = This->resource.size; /* dx8 only */
217 pDesc->Width = This->currentDesc.Width;
218 pDesc->Height = This->currentDesc.Height;
219 pDesc->Depth = This->currentDesc.Depth;
220
221 return WINED3D_OK;
222}
223
224static HRESULT WINAPI IWineD3DVolumeImpl_LockBox(IWineD3DVolume *iface, WINED3DLOCKED_BOX* pLockedVolume, CONST WINED3DBOX* pBox, DWORD Flags) {
225 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
226 FIXME("(%p) : pBox=%p stub\n", This, pBox);
227
228 if(!This->resource.allocatedMemory) {
229 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->resource.size);
230 }
231
232 /* fixme: should we really lock as such? */
233 TRACE("(%p) : box=%p, output pbox=%p, allMem=%p\n", This, pBox, pLockedVolume, This->resource.allocatedMemory);
234
235 pLockedVolume->RowPitch = This->resource.format_desc->byte_count * This->currentDesc.Width; /* Bytes / row */
236 pLockedVolume->SlicePitch = This->resource.format_desc->byte_count
237 * This->currentDesc.Width * This->currentDesc.Height; /* Bytes / slice */
238 if (!pBox) {
239 TRACE("No box supplied - all is ok\n");
240 pLockedVolume->pBits = This->resource.allocatedMemory;
241 This->lockedBox.Left = 0;
242 This->lockedBox.Top = 0;
243 This->lockedBox.Front = 0;
244 This->lockedBox.Right = This->currentDesc.Width;
245 This->lockedBox.Bottom = This->currentDesc.Height;
246 This->lockedBox.Back = This->currentDesc.Depth;
247 } else {
248 TRACE("Lock Box (%p) = l %d, t %d, r %d, b %d, fr %d, ba %d\n", pBox, pBox->Left, pBox->Top, pBox->Right, pBox->Bottom, pBox->Front, pBox->Back);
249 pLockedVolume->pBits = This->resource.allocatedMemory
250 + (pLockedVolume->SlicePitch * pBox->Front) /* FIXME: is front < back or vica versa? */
251 + (pLockedVolume->RowPitch * pBox->Top)
252 + (pBox->Left * This->resource.format_desc->byte_count);
253 This->lockedBox.Left = pBox->Left;
254 This->lockedBox.Top = pBox->Top;
255 This->lockedBox.Front = pBox->Front;
256 This->lockedBox.Right = pBox->Right;
257 This->lockedBox.Bottom = pBox->Bottom;
258 This->lockedBox.Back = pBox->Back;
259 }
260
261 if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
262 /* Don't dirtify */
263 } else {
264 /**
265 * Dirtify on lock
266 * as seen in msdn docs
267 */
268 volume_add_dirty_box(iface, &This->lockedBox);
269
270 /** Dirtify Container if needed */
271 if (NULL != This->container) {
272
273 IWineD3DVolumeTexture *cont = (IWineD3DVolumeTexture*) This->container;
274 WINED3DRESOURCETYPE containerType = IWineD3DBaseTexture_GetType((IWineD3DBaseTexture *) cont);
275
276 if (containerType == WINED3DRTYPE_VOLUMETEXTURE) {
277 IWineD3DBaseTextureImpl* pTexture = (IWineD3DBaseTextureImpl*) cont;
278 pTexture->baseTexture.texture_rgb.dirty = TRUE;
279 pTexture->baseTexture.texture_srgb.dirty = TRUE;
280 } else {
281 FIXME("Set dirty on container type %d\n", containerType);
282 }
283 }
284 }
285
286 This->locked = TRUE;
287 TRACE("returning memory@%p rpitch(%d) spitch(%d)\n", pLockedVolume->pBits, pLockedVolume->RowPitch, pLockedVolume->SlicePitch);
288 return WINED3D_OK;
289}
290
291static HRESULT WINAPI IWineD3DVolumeImpl_UnlockBox(IWineD3DVolume *iface) {
292 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
293 if (!This->locked) {
294 ERR("trying to lock unlocked volume@%p\n", This);
295 return WINED3DERR_INVALIDCALL;
296 }
297 TRACE("(%p) : unlocking volume\n", This);
298 This->locked = FALSE;
299 memset(&This->lockedBox, 0, sizeof(RECT));
300 return WINED3D_OK;
301}
302
303/* Internal use functions follow : */
304
305static HRESULT WINAPI IWineD3DVolumeImpl_SetContainer(IWineD3DVolume *iface, IWineD3DBase* container) {
306 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
307
308 TRACE("This %p, container %p\n", This, container);
309
310 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
311
312 TRACE("Setting container to %p from %p\n", container, This->container);
313 This->container = container;
314
315 return WINED3D_OK;
316}
317
318/* Context activation is done by the caller. */
319static HRESULT WINAPI IWineD3DVolumeImpl_LoadTexture(IWineD3DVolume *iface, int gl_level, BOOL srgb_mode) {
320 IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
321 const struct GlPixelFormatDesc *glDesc = This->resource.format_desc;
322
323 TRACE("(%p) : level %u, format %s (0x%08x)\n", This, gl_level, debug_d3dformat(glDesc->format), glDesc->format);
324
325 volume_bind_and_dirtify(iface);
326
327 TRACE("Calling glTexImage3D %x level=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%x, Mem=%p\n",
328 GL_TEXTURE_3D,
329 gl_level,
330 glDesc->glInternal,
331 This->currentDesc.Width,
332 This->currentDesc.Height,
333 This->currentDesc.Depth,
334 0,
335 glDesc->glFormat,
336 glDesc->glType,
337 This->resource.allocatedMemory);
338
339 ENTER_GL();
340 GL_EXTCALL(glTexImage3DEXT(GL_TEXTURE_3D,
341 gl_level,
342 glDesc->glInternal,
343 This->currentDesc.Width,
344 This->currentDesc.Height,
345 This->currentDesc.Depth,
346 0,
347 glDesc->glFormat,
348 glDesc->glType,
349 This->resource.allocatedMemory));
350 checkGLcall("glTexImage3D");
351 LEAVE_GL();
352
353 /* When adding code releasing This->resource.allocatedMemory to save data keep in mind that
354 * GL_UNPACK_CLIENT_STORAGE_APPLE is enabled by default if supported(GL_APPLE_client_storage).
355 * Thus do not release This->resource.allocatedMemory if GL_APPLE_client_storage is supported.
356 */
357 return WINED3D_OK;
358
359}
360
361static const IWineD3DVolumeVtbl IWineD3DVolume_Vtbl =
362{
363 /* IUnknown */
364 IWineD3DVolumeImpl_QueryInterface,
365 IWineD3DVolumeImpl_AddRef,
366 IWineD3DVolumeImpl_Release,
367 /* IWineD3DResource */
368 IWineD3DVolumeImpl_GetParent,
369 IWineD3DVolumeImpl_GetDevice,
370 IWineD3DVolumeImpl_SetPrivateData,
371 IWineD3DVolumeImpl_GetPrivateData,
372 IWineD3DVolumeImpl_FreePrivateData,
373 IWineD3DVolumeImpl_SetPriority,
374 IWineD3DVolumeImpl_GetPriority,
375 IWineD3DVolumeImpl_PreLoad,
376 IWineD3DVolumeImpl_UnLoad,
377 IWineD3DVolumeImpl_GetType,
378 /* IWineD3DVolume */
379 IWineD3DVolumeImpl_GetContainer,
380 IWineD3DVolumeImpl_GetDesc,
381 IWineD3DVolumeImpl_LockBox,
382 IWineD3DVolumeImpl_UnlockBox,
383 /* Internal interface */
384 IWineD3DVolumeImpl_LoadTexture,
385 IWineD3DVolumeImpl_SetContainer
386};
387
388HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT width,
389 UINT height, UINT depth, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool,
390 IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
391{
392 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
393 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, gl_info);
394 HRESULT hr;
395
396 if (!gl_info->supported[EXT_TEXTURE3D])
397 {
398 WARN("Volume cannot be created - no volume texture support.\n");
399 return WINED3DERR_INVALIDCALL;
400 }
401
402 volume->lpVtbl = &IWineD3DVolume_Vtbl;
403
404 hr = resource_init((IWineD3DResource *)volume, WINED3DRTYPE_VOLUME, device,
405 width * height * depth * format_desc->byte_count, usage, format_desc, pool, parent, parent_ops);
406 if (FAILED(hr))
407 {
408 WARN("Failed to initialize resource, returning %#x.\n", hr);
409 return hr;
410 }
411
412 volume->currentDesc.Width = width;
413 volume->currentDesc.Height = height;
414 volume->currentDesc.Depth = depth;
415 volume->lockable = TRUE;
416 volume->locked = FALSE;
417 memset(&volume->lockedBox, 0, sizeof(volume->lockedBox));
418 volume->dirty = TRUE;
419
420 volume_add_dirty_box((IWineD3DVolume *)volume, NULL);
421
422 return WINED3D_OK;
423}
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