| // |
| // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // Surface.cpp: Implements the egl::Surface class, representing a drawing surface |
| // such as the client area of a window, including any back buffers. |
| // Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. |
| |
| #include "libEGL/Surface.h" |
| |
| #include "common/debug.h" |
| |
| #include "libEGL/main.h" |
| #include "libEGL/Display.h" |
| |
| namespace egl |
| { |
| Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurface9 *depthStencil, const Config *config) |
| : mDisplay(display), mSwapChain(swapChain), mDepthStencil(depthStencil), mConfig(config) |
| { |
| mBackBuffer = NULL; |
| mRenderTarget = NULL; |
| |
| mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio |
| mRenderBuffer = EGL_BACK_BUFFER; |
| mSwapBehavior = EGL_BUFFER_PRESERVED; |
| |
| if (mSwapChain) |
| { |
| mSwapChain->AddRef(); |
| mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); |
| |
| D3DSURFACE_DESC description; |
| mBackBuffer->GetDesc(&description); |
| |
| mWidth = description.Width; |
| mHeight = description.Height; |
| |
| IDirect3DDevice9 *device = display->getDevice(); |
| HRESULT result = device->CreateRenderTarget(mWidth, mHeight, description.Format, description.MultiSampleType, description.MultiSampleQuality, FALSE, &mRenderTarget, NULL); |
| |
| if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) |
| { |
| error(EGL_BAD_ALLOC); |
| |
| return; |
| } |
| |
| ASSERT(SUCCEEDED(result)); |
| } |
| } |
| |
| Surface::~Surface() |
| { |
| if (mSwapChain) |
| { |
| mSwapChain->Release(); |
| } |
| |
| if (mBackBuffer) |
| { |
| mBackBuffer->Release(); |
| } |
| |
| if (mRenderTarget) |
| { |
| mRenderTarget->Release(); |
| } |
| |
| if (mDepthStencil) |
| { |
| mDepthStencil->Release(); |
| } |
| } |
| |
| HWND Surface::getWindowHandle() |
| { |
| if (mSwapChain) |
| { |
| D3DPRESENT_PARAMETERS presentParameters; |
| mSwapChain->GetPresentParameters(&presentParameters); |
| |
| return presentParameters.hDeviceWindow; |
| } |
| |
| return NULL; |
| } |
| |
| void Surface::swap() |
| { |
| if (mSwapChain) |
| { |
| IDirect3DDevice9 *device = mDisplay->getDevice(); |
| D3DSURFACE_DESC description; |
| mBackBuffer->GetDesc(&description); |
| |
| // Copy the render target into a texture |
| IDirect3DTexture9 *texture; |
| HRESULT result = device->CreateTexture(mWidth, mHeight, 1, D3DUSAGE_RENDERTARGET, description.Format, D3DPOOL_DEFAULT, &texture, NULL); |
| |
| if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) |
| { |
| return error(EGL_BAD_ALLOC); |
| } |
| |
| ASSERT(SUCCEEDED(result)); |
| |
| IDirect3DSurface9 *textureSurface; |
| texture->GetSurfaceLevel(0, &textureSurface); |
| |
| mDisplay->endScene(); |
| device->StretchRect(mRenderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE); |
| |
| // Disable all pipeline operations |
| device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); |
| device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); |
| device->SetRenderState(D3DRS_ALPHATESTENABLE , FALSE); |
| device->SetRenderState(D3DRS_ALPHABLENDENABLE , FALSE); |
| device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); |
| device->SetRenderState(D3DRS_STENCILENABLE, FALSE); |
| device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); |
| device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); |
| device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); |
| device->SetPixelShader(NULL); |
| device->SetVertexShader(NULL); |
| |
| // Just sample the texture |
| device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); |
| device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); |
| device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); |
| device->SetTexture(0, texture); |
| device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); |
| device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); |
| device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); |
| device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); |
| device->SetRenderTarget(0, mBackBuffer); |
| |
| // Render the texture upside down into the back buffer |
| float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f}, |
| {mWidth - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 1.0f, 1.0f}, |
| {mWidth - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 1.0f, 0.0f}, |
| { 0 - 0.5f, mHeight - 0.5f, 0.0f, 1.0f, 0.0f, 0.0f}}; // x, y, z, rhw, u, v |
| |
| mDisplay->startScene(); |
| device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); |
| |
| textureSurface->Release(); |
| texture->Release(); |
| |
| mDisplay->endScene(); |
| result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval(mConfig, false)); |
| |
| if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) |
| { |
| return error(EGL_BAD_ALLOC); |
| } |
| } |
| } |
| |
| EGLint Surface::getWidth() const |
| { |
| return mWidth; |
| } |
| |
| EGLint Surface::getHeight() const |
| { |
| return mHeight; |
| } |
| |
| IDirect3DSurface9 *Surface::getRenderTarget() |
| { |
| if (mRenderTarget) |
| { |
| mRenderTarget->AddRef(); |
| } |
| |
| return mRenderTarget; |
| } |
| |
| IDirect3DSurface9 *Surface::getDepthStencil() |
| { |
| if (mDepthStencil) |
| { |
| mDepthStencil->AddRef(); |
| } |
| |
| return mDepthStencil; |
| } |
| } |