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