1 #include "precompiled.h" 2 // 3 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 8 // RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 9 // pointers retained by renderbuffers. 10 11 #include "libGLESv2/renderer/d3d9/RenderTarget9.h" 12 #include "libGLESv2/renderer/d3d9/Renderer9.h" 13 14 #include "libGLESv2/renderer/d3d9/renderer9_utils.h" 15 #include "libGLESv2/renderer/d3d9/formatutils9.h" 16 #include "libGLESv2/main.h" 17 18 namespace rx 19 { 20 21 // TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. 22 RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) 23 { 24 mRenderer = Renderer9::makeRenderer9(renderer); 25 mRenderTarget = surface; 26 27 if (mRenderTarget) 28 { 29 D3DSURFACE_DESC description; 30 mRenderTarget->GetDesc(&description); 31 32 mWidth = description.Width; 33 mHeight = description.Height; 34 mDepth = 1; 35 36 mInternalFormat = d3d9_gl::GetInternalFormat(description.Format); 37 mActualFormat = d3d9_gl::GetInternalFormat(description.Format); 38 mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType); 39 } 40 } 41 42 RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) 43 { 44 mRenderer = Renderer9::makeRenderer9(renderer); 45 mRenderTarget = NULL; 46 47 D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat, mRenderer); 48 int supportedSamples = mRenderer->getNearestSupportedSamples(renderFormat, samples); 49 50 if (supportedSamples == -1) 51 { 52 gl::error(GL_OUT_OF_MEMORY); 53 54 return; 55 } 56 57 HRESULT result = D3DERR_INVALIDCALL; 58 59 GLuint clientVersion = mRenderer->getCurrentClientVersion(); 60 61 if (width > 0 && height > 0) 62 { 63 IDirect3DDevice9 *device = mRenderer->getDevice(); 64 65 bool requiresInitialization = false; 66 67 if (gl::GetDepthBits(internalFormat, clientVersion) > 0 || 68 gl::GetStencilBits(internalFormat, clientVersion) > 0) 69 { 70 result = device->CreateDepthStencilSurface(width, height, renderFormat, 71 gl_d3d9::GetMultisampleType(supportedSamples), 72 0, FALSE, &mRenderTarget, NULL); 73 } 74 else 75 { 76 requiresInitialization = gl_d3d9::RequiresTextureDataInitialization(internalFormat); 77 78 result = device->CreateRenderTarget(width, height, renderFormat, 79 gl_d3d9::GetMultisampleType(supportedSamples), 80 0, FALSE, &mRenderTarget, NULL); 81 } 82 83 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) 84 { 85 gl::error(GL_OUT_OF_MEMORY); 86 87 return; 88 } 89 90 ASSERT(SUCCEEDED(result)); 91 92 if (requiresInitialization) 93 { 94 // This format requires that the data be initialized before the render target can be used 95 // Unfortunately this requires a Get call on the d3d device but it is far better than having 96 // to mark the render target as lockable and copy data to the gpu. 97 IDirect3DSurface9 *prevRenderTarget = NULL; 98 device->GetRenderTarget(0, &prevRenderTarget); 99 device->SetRenderTarget(0, mRenderTarget); 100 device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); 101 device->SetRenderTarget(0, prevRenderTarget); 102 } 103 } 104 105 mWidth = width; 106 mHeight = height; 107 mDepth = 1; 108 mInternalFormat = internalFormat; 109 mSamples = supportedSamples; 110 mActualFormat = d3d9_gl::GetInternalFormat(renderFormat); 111 } 112 113 RenderTarget9::~RenderTarget9() 114 { 115 SafeRelease(mRenderTarget); 116 } 117 118 RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) 119 { 120 ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); 121 return static_cast<rx::RenderTarget9*>(target); 122 } 123 124 void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) 125 { 126 // Currently a no-op 127 } 128 129 IDirect3DSurface9 *RenderTarget9::getSurface() 130 { 131 // Caller is responsible for releasing the returned surface reference. 132 // TODO: remove the AddRef to match RenderTarget11 133 if (mRenderTarget) 134 { 135 mRenderTarget->AddRef(); 136 } 137 138 return mRenderTarget; 139 } 140 141 } 142