source: OGRE/trunk/ogrenew/RenderSystems/Direct3D9/src/OgreD3D9HardwarePixelBuffer.cpp @ 657

Revision 657, 14.4 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreD3D9HardwarePixelBuffer.h"
26#include "OgreD3D9Texture.h"
27#include "OgreException.h"
28#include "OgreLogManager.h"
29#include "OgreStringConverter.h"
30#include "OgreBitwise.h"
31
32#include "OgreNoMemoryMacros.h"
33#include <d3dx9.h>
34#include <dxerr9.h>
35#include "OgreMemoryMacros.h"
36
37namespace Ogre {
38
39//----------------------------------------------------------------------------- 
40
41D3D9HardwarePixelBuffer::D3D9HardwarePixelBuffer(HardwareBuffer::Usage usage):
42        HardwarePixelBuffer(0, 0, 0, PF_UNKNOWN, usage, false, false),
43        mpDev(0),
44        mSurface(0), mVolume(0), mTempSurface(0), mTempVolume(0),
45        mDoMipmapGen(0), mHWMipmaps(0), mMipTex(0)
46{
47}
48D3D9HardwarePixelBuffer::~D3D9HardwarePixelBuffer()
49{
50}
51//----------------------------------------------------------------------------- 
52void D3D9HardwarePixelBuffer::bind(IDirect3DDevice9 *dev, IDirect3DSurface9 *surface)
53{
54        mpDev = dev;
55        mSurface = surface;
56       
57        D3DSURFACE_DESC desc;
58        if(mSurface->GetDesc(&desc) != D3D_OK)
59                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Could not get surface information",
60                 "D3D9HardwarePixelBuffer::D3D9HardwarePixelBuffer");
61        mWidth = desc.Width;
62        mHeight = desc.Height;
63        mDepth = 1;
64        mFormat = D3D9Texture::_getPF(desc.Format);
65        // Default
66        mRowPitch = mWidth;
67        mSlicePitch = mHeight*mWidth;
68        mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
69}
70//-----------------------------------------------------------------------------
71void D3D9HardwarePixelBuffer::bind(IDirect3DDevice9 *dev, IDirect3DVolume9 *volume)
72{
73        mpDev = dev;
74        mVolume = volume;
75       
76        D3DVOLUME_DESC desc;
77        if(mVolume->GetDesc(&desc) != D3D_OK)
78                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Could not get volume information",
79                 "D3D9HardwarePixelBuffer::D3D9HardwarePixelBuffer");
80        mWidth = desc.Width;
81        mHeight = desc.Height;
82        mDepth = desc.Depth;
83        mFormat = D3D9Texture::_getPF(desc.Format);
84        // Default
85        mRowPitch = mWidth;
86        mSlicePitch = mHeight*mWidth;
87        mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
88}
89//----------------------------------------------------------------------------- 
90// Util functions to convert a D3D locked box to a pixel box
91void fromD3DLock(PixelBox &rval, const D3DLOCKED_RECT &lrect)
92{
93        rval.rowPitch = lrect.Pitch / PixelUtil::getNumElemBytes(rval.format);
94        rval.slicePitch = rval.rowPitch * rval.getHeight();
95        assert((lrect.Pitch % PixelUtil::getNumElemBytes(rval.format))==0);
96        rval.data = lrect.pBits;
97}
98void fromD3DLock(PixelBox &rval, const D3DLOCKED_BOX &lbox)
99{
100        rval.rowPitch = lbox.RowPitch / PixelUtil::getNumElemBytes(rval.format);
101        rval.slicePitch = lbox.SlicePitch / PixelUtil::getNumElemBytes(rval.format);
102        assert((lbox.RowPitch % PixelUtil::getNumElemBytes(rval.format))==0);
103        assert((lbox.SlicePitch % PixelUtil::getNumElemBytes(rval.format))==0);
104        rval.data = lbox.pBits;
105}
106// Convert Ogre integer Box to D3D rectangle
107RECT toD3DRECT(const Box &lockBox)
108{
109        RECT prect;
110        assert(lockBox.getDepth() == 1);
111        prect.left = lockBox.left;
112        prect.right = lockBox.right;
113        prect.top = lockBox.top;
114        prect.bottom = lockBox.bottom;
115        return prect;
116}
117// Convert Ogre integer Box to D3D box
118D3DBOX toD3DBOX(const Box &lockBox)
119{
120        D3DBOX pbox;
121        pbox.Left = lockBox.left;
122        pbox.Right = lockBox.right;
123        pbox.Top = lockBox.top;
124        pbox.Bottom = lockBox.bottom;
125        pbox.Front = lockBox.front;
126        pbox.Back = lockBox.back;
127        return pbox;
128}
129// Convert Ogre pixelbox extent to D3D rectangle
130RECT toD3DRECTExtent(const PixelBox &lockBox)
131{
132        RECT prect;
133        assert(lockBox.getDepth() == 1);
134        prect.left = 0;
135        prect.right = lockBox.getWidth();
136        prect.top = 0;
137        prect.bottom = lockBox.getHeight();
138        return prect;
139}
140// Convert Ogre pixelbox extent to D3D box
141D3DBOX toD3DBOXExtent(const PixelBox &lockBox)
142{
143        D3DBOX pbox;
144        pbox.Left = 0;
145        pbox.Right = lockBox.getWidth();
146        pbox.Top = 0;
147        pbox.Bottom = lockBox.getHeight();
148        pbox.Front = 0;
149        pbox.Back = lockBox.getDepth();
150        return pbox;
151}
152//----------------------------------------------------------------------------- 
153PixelBox D3D9HardwarePixelBuffer::lockImpl(const Image::Box lockBox,  LockOptions options)
154{
155        // Set extents and format
156        PixelBox rval(lockBox, mFormat);
157        // Set locking flags according to options
158        DWORD flags = 0;
159        switch(options)
160        {
161        case HBL_DISCARD:
162                // D3D only likes D3DLOCK_DISCARD if you created the texture with D3DUSAGE_DYNAMIC
163                // debug runtime flags this up, could cause problems on some drivers
164                if (mUsage & HBU_DYNAMIC)
165                        flags |= D3DLOCK_DISCARD;
166                break;
167        case HBL_READ_ONLY:
168                flags |= D3DLOCK_READONLY;
169                break;
170        default:
171                break;
172        };
173       
174        if(mSurface)
175        {
176                // Surface
177                D3DLOCKED_RECT lrect; // Filled in by D3D
178                HRESULT hr;
179
180                if (lockBox.left == 0 && lockBox.top == 0
181                        && lockBox.right == mWidth && lockBox.bottom == mHeight)
182                {
183                        // Lock whole surface
184                        hr = mSurface->LockRect(&lrect, NULL, flags);
185                }
186                else
187                {
188                        RECT prect = toD3DRECT(lockBox); // specify range to lock
189                        hr = mSurface->LockRect(&lrect, &prect, flags);
190                }
191                if (FAILED(hr))         
192                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Surface locking failed",
193                                "D3D9HardwarePixelBuffer::lockImpl");
194                fromD3DLock(rval, lrect);
195        }
196        else
197        {
198                // Volume
199                D3DBOX pbox = toD3DBOX(lockBox); // specify range to lock
200                D3DLOCKED_BOX lbox; // Filled in by D3D
201               
202                if(mVolume->LockBox(&lbox, &pbox, flags) != D3D_OK)
203                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Volume locking failed",
204                                "D3D9HardwarePixelBuffer::lockImpl");
205                fromD3DLock(rval, lbox);
206        }
207
208        return rval;
209}
210//----------------------------------------------------------------------------- 
211void D3D9HardwarePixelBuffer::unlockImpl(void)
212{
213        if(mSurface)
214        {
215                // Surface
216                mSurface->UnlockRect();
217        } else {
218                // Volume
219                mVolume->UnlockBox();
220        }
221        if(mDoMipmapGen)
222                _genMipmaps();
223}
224//----------------------------------------------------------------------------- 
225void D3D9HardwarePixelBuffer::blit(HardwarePixelBuffer *rsrc, const Image::Box &srcBox, const Image::Box &dstBox)
226{
227        D3D9HardwarePixelBuffer *src = static_cast<D3D9HardwarePixelBuffer*>(rsrc);
228        if(mSurface && src->mSurface)
229        {
230                // Surface-to-surface
231                RECT dsrcRect = toD3DRECT(srcBox);
232                RECT ddestRect = toD3DRECT(dstBox);
233                // D3DXLoadSurfaceFromSurface
234                if(D3DXLoadSurfaceFromSurface(
235                        mSurface, NULL, &ddestRect,
236                        src->mSurface, NULL, &dsrcRect,
237                         D3DX_DEFAULT, 0) != D3D_OK)
238                {
239                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "D3DXLoadSurfaceFromSurface failed",
240                                "D3D9HardwarePixelBuffer::blit");
241                }
242        }
243        else if(mVolume && src->mVolume)
244        {
245                // Volume-to-volume
246                D3DBOX dsrcBox = toD3DBOX(srcBox);
247                D3DBOX ddestBox = toD3DBOX(dstBox);
248               
249                // D3DXLoadVolumeFromVolume
250                if(D3DXLoadVolumeFromVolume(
251                        mVolume, NULL, &ddestBox,
252                        src->mVolume, NULL, &dsrcBox,
253                         D3DX_DEFAULT, 0) != D3D_OK)
254                {
255                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "D3DXLoadVolumeFromVolume failed",
256                                "D3D9HardwarePixelBuffer::blit");
257                }
258        }
259        else
260        {
261                HardwarePixelBuffer::blit(src, srcBox, dstBox);
262        }
263}
264//----------------------------------------------------------------------------- 
265void D3D9HardwarePixelBuffer::blitFromMemory(const PixelBox &src, const Image::Box &dstBox)
266{
267        // for scoped deletion of conversion buffer
268        MemoryDataStreamPtr buf;
269        PixelBox converted = src;
270
271        // convert to pixelbuffer's native format if necessary
272        if (D3D9Texture::_getPF(src.format) == D3DFMT_UNKNOWN)
273        {
274                buf.bind(new MemoryDataStream(
275                        PixelUtil::getMemorySize(src.getWidth(), src.getHeight(), src.getDepth(),
276                                                                                mFormat)));
277                converted = PixelBox(src.getWidth(), src.getHeight(), src.getDepth(), mFormat, buf->getPtr());
278                PixelUtil::bulkPixelConversion(src, converted);
279        }
280
281        if(mSurface)
282        {
283                RECT destRect, srcRect;
284                srcRect = toD3DRECTExtent(converted);
285                destRect = toD3DRECT(dstBox);
286               
287                if(D3DXLoadSurfaceFromMemory(mSurface, NULL, &destRect,
288                        converted.data, D3D9Texture::_getPF(converted.format),
289                        converted.rowPitch * PixelUtil::getNumElemBytes(converted.format),
290                        NULL, &srcRect, D3DX_DEFAULT, 0) != D3D_OK)
291                {
292                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "D3DXLoadSurfaceFromMemory failed",
293                                "D3D9HardwarePixelBuffer::blitFromMemory");
294                }
295        }
296        else
297        {
298                D3DBOX destBox, srcBox;
299                srcBox = toD3DBOXExtent(converted);
300                destBox = toD3DBOX(dstBox);
301               
302                if(D3DXLoadVolumeFromMemory(mVolume, NULL, &destBox,
303                        converted.data, D3D9Texture::_getPF(converted.format),
304                        converted.rowPitch * PixelUtil::getNumElemBytes(converted.format),
305                        converted.slicePitch * PixelUtil::getNumElemBytes(converted.format),
306                        NULL, &srcBox, D3DX_DEFAULT, 0) != D3D_OK)
307                {
308                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "D3DXLoadSurfaceFromMemory failed",
309                                "D3D9HardwarePixelBuffer::blitFromMemory");
310                }
311        }
312        if(mDoMipmapGen)
313                _genMipmaps();
314}
315//----------------------------------------------------------------------------- 
316void D3D9HardwarePixelBuffer::blitToMemory(const Image::Box &srcBox, const PixelBox &dst)
317{
318        // Decide on pixel format of temp surface
319        PixelFormat tmpFormat = mFormat;
320        if(D3D9Texture::_getPF(dst.format) != D3DFMT_UNKNOWN)
321        {
322                tmpFormat = dst.format;
323        }
324        if(mSurface)
325        {
326                assert(srcBox.getDepth() == 1 && dst.getDepth() == 1);
327                // Create temp texture
328                IDirect3DTexture9 *tmp;
329                IDirect3DSurface9 *surface;
330       
331                if(D3DXCreateTexture(
332                        mpDev,
333                        dst.getWidth(), dst.getHeight(),
334                        1, // 1 mip level ie topmost, generate no mipmaps
335                        0, D3D9Texture::_getPF(tmpFormat), D3DPOOL_SCRATCH,
336                        &tmp
337                        ) != D3D_OK)
338                {
339                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Create temporary texture failed",
340                                "D3D9HardwarePixelBuffer::blitToMemory");
341                }
342                if(tmp->GetSurfaceLevel(0, &surface) != D3D_OK)
343                {
344                        tmp->Release();
345                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Get surface level failed",
346                                "D3D9HardwarePixelBuffer::blitToMemory");
347                }
348                // Copy texture to this temp surface
349                RECT destRect, srcRect;
350                srcRect = toD3DRECT(srcBox);
351                destRect = toD3DRECTExtent(dst);
352               
353                if(D3DXLoadSurfaceFromSurface(
354                        surface, NULL, &destRect,
355                        mSurface, NULL, &srcRect,
356                         D3DX_DEFAULT, 0) != D3D_OK)
357                {
358                        surface->Release();
359                        tmp->Release();
360                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "D3DXLoadSurfaceFromSurface failed",
361                                "D3D9HardwarePixelBuffer::blitToMemory");
362                }
363                // Lock temp surface and copy it to memory
364                D3DLOCKED_RECT lrect; // Filled in by D3D
365                if(surface->LockRect(&lrect, NULL,  D3DLOCK_READONLY) != D3D_OK)
366                {
367                        surface->Release();
368                        tmp->Release();
369                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "surface->LockRect",
370                                "D3D9HardwarePixelBuffer::blitToMemory");
371                }
372                // Copy it
373                PixelBox locked(dst.getWidth(), dst.getHeight(), dst.getDepth(), tmpFormat);
374                fromD3DLock(locked, lrect);
375                PixelUtil::bulkPixelConversion(locked, dst);
376                surface->UnlockRect();
377                // Release temporary surface and texture
378                surface->Release();
379                tmp->Release();
380        }
381        else
382        {
383                // Create temp texture
384                IDirect3DVolumeTexture9 *tmp;
385                IDirect3DVolume9 *surface;
386       
387                if(D3DXCreateVolumeTexture(
388                        mpDev,
389                        dst.getWidth(), dst.getHeight(), dst.getDepth(), 0,
390                        0, D3D9Texture::_getPF(tmpFormat), D3DPOOL_SCRATCH,
391                        &tmp
392                        ) != D3D_OK)
393                {
394                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Create temporary texture failed",
395                                "D3D9HardwarePixelBuffer::blitToMemory");
396                }
397                if(tmp->GetVolumeLevel(0, &surface) != D3D_OK)
398                {
399                        tmp->Release();
400                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Get volume level failed",
401                                "D3D9HardwarePixelBuffer::blitToMemory");
402                }
403                // Volume
404                D3DBOX ddestBox, dsrcBox;
405                ddestBox = toD3DBOXExtent(dst);
406                dsrcBox = toD3DBOX(srcBox);
407               
408                if(D3DXLoadVolumeFromVolume(
409                        surface, NULL, &ddestBox,
410                        mVolume, NULL, &dsrcBox,
411                         D3DX_DEFAULT, 0) != D3D_OK)
412                {
413                        surface->Release();
414                        tmp->Release();
415                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "D3DXLoadVolumeFromVolume failed",
416                                "D3D9HardwarePixelBuffer::blitToMemory");
417                }
418                // Lock temp surface and copy it to memory
419                D3DLOCKED_BOX lbox; // Filled in by D3D
420                if(surface->LockBox(&lbox, NULL,  D3DLOCK_READONLY) != D3D_OK)
421                {
422                        surface->Release();
423                        tmp->Release();
424                        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "surface->LockBox",
425                                "D3D9HardwarePixelBuffer::blitToMemory");
426                }
427                // Copy it
428                PixelBox locked(dst.getWidth(), dst.getHeight(), dst.getDepth(), tmpFormat);
429                fromD3DLock(locked, lbox);
430                PixelUtil::bulkPixelConversion(locked, dst);
431                surface->UnlockBox();
432                // Release temporary surface and texture
433                surface->Release();
434                tmp->Release();
435        }
436}
437//----------------------------------------------------------------------------- 
438void D3D9HardwarePixelBuffer::_genMipmaps()
439{
440        assert(mMipTex);
441        // Mipmapping
442        if (mHWMipmaps)
443        {
444                // Hardware mipmaps
445                mMipTex->GenerateMipSubLevels();
446        }
447        else
448        {
449                // Software mipmaps
450                if( D3DXFilterTexture( mMipTex, NULL, D3DX_DEFAULT, D3DX_DEFAULT ) != D3D_OK )
451                {
452                        OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR,
453                        "Failed to filter texture (generate mipmaps)",
454                         "D3D9HardwarePixelBuffer::_genMipmaps" );
455                }
456        }
457
458}
459//-----------------------------------------------------------------------------
460void D3D9HardwarePixelBuffer::_setMipmapping(bool doMipmapGen, bool HWMipmaps, IDirect3DBaseTexture9 *mipTex)
461{
462        mDoMipmapGen = doMipmapGen;
463        mHWMipmaps = HWMipmaps;
464        mMipTex = mipTex;
465}
466
467
468};
Note: See TracBrowser for help on using the repository browser.