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