Home | History | Annotate | Download | only in d3d9
      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