Home | History | Annotate | Download | only in renderer
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2012-2013 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 // Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
      9 
     10 #include <EGL/eglext.h>
     11 #include "libGLESv2/main.h"
     12 #include "libGLESv2/Program.h"
     13 #include "libGLESv2/renderer/Renderer.h"
     14 #include "libGLESv2/renderer/Renderer9.h"
     15 #include "libGLESv2/renderer/Renderer11.h"
     16 #include "libGLESv2/utilities.h"
     17 
     18 #if !defined(ANGLE_ENABLE_D3D11)
     19 // Enables use of the Direct3D 11 API for a default display, when available
     20 #define ANGLE_ENABLE_D3D11 0
     21 #endif
     22 
     23 namespace rx
     24 {
     25 
     26 Renderer::Renderer(egl::Display *display) : mDisplay(display)
     27 {
     28     mD3dCompilerModule = NULL;
     29     mD3DCompileFunc = NULL;
     30 }
     31 
     32 Renderer::~Renderer()
     33 {
     34     if (mD3dCompilerModule)
     35     {
     36         FreeLibrary(mD3dCompilerModule);
     37         mD3dCompilerModule = NULL;
     38     }
     39 }
     40 
     41 bool Renderer::initializeCompiler()
     42 {
     43 #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
     44     // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
     45     static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
     46 
     47     for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
     48     {
     49         if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule))
     50         {
     51             break;
     52         }
     53     }
     54 #else
     55     // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
     56     mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
     57 #endif  // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
     58 
     59     if (!mD3dCompilerModule)
     60     {
     61         ERR("No D3D compiler module found - aborting!\n");
     62         return false;
     63     }
     64 
     65     mD3DCompileFunc = reinterpret_cast<pCompileFunc>(GetProcAddress(mD3dCompilerModule, "D3DCompile"));
     66     ASSERT(mD3DCompileFunc);
     67 
     68     return mD3DCompileFunc != NULL;
     69 }
     70 
     71 // Compiles HLSL code into executable binaries
     72 ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags)
     73 {
     74     if (!hlsl)
     75     {
     76         return NULL;
     77     }
     78 
     79     HRESULT result = S_OK;
     80     UINT flags = 0;
     81     std::string sourceText;
     82     if (gl::perfActive())
     83     {
     84         flags |= D3DCOMPILE_DEBUG;
     85 
     86 #ifdef NDEBUG
     87         flags |= optimizationFlags;
     88 #else
     89         flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
     90 #endif
     91 
     92         std::string sourcePath = getTempPath();
     93         sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
     94         writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
     95     }
     96     else
     97     {
     98         flags |= optimizationFlags;
     99         sourceText = hlsl;
    100     }
    101 
    102     // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
    103     // Try the default flags first and if compilation fails, try some alternatives.
    104     const static UINT extraFlags[] =
    105     {
    106         0,
    107         D3DCOMPILE_AVOID_FLOW_CONTROL,
    108         D3DCOMPILE_PREFER_FLOW_CONTROL
    109     };
    110 
    111     const static char * const extraFlagNames[] =
    112     {
    113         "default",
    114         "avoid flow control",
    115         "prefer flow control"
    116     };
    117 
    118     int attempts = alternateFlags ? ArraySize(extraFlags) : 1;
    119     pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
    120     for (int i = 0; i < attempts; ++i)
    121     {
    122         ID3DBlob *errorMessage = NULL;
    123         ID3DBlob *binary = NULL;
    124 
    125         result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL,
    126                              "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage);
    127         if (errorMessage)
    128         {
    129             const char *message = (const char*)errorMessage->GetBufferPointer();
    130 
    131             infoLog.appendSanitized(message);
    132             TRACE("\n%s", hlsl);
    133             TRACE("\n%s", message);
    134 
    135             errorMessage->Release();
    136             errorMessage = NULL;
    137         }
    138 
    139         if (SUCCEEDED(result))
    140         {
    141             return (ShaderBlob*)binary;
    142         }
    143         else
    144         {
    145             if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
    146             {
    147                 return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL);
    148             }
    149 
    150             infoLog.append("Warning: D3D shader compilation failed with ");
    151             infoLog.append(extraFlagNames[i]);
    152             infoLog.append(" flags.");
    153             if (i + 1 < attempts)
    154             {
    155                 infoLog.append(" Retrying with ");
    156                 infoLog.append(extraFlagNames[i + 1]);
    157                 infoLog.append(".\n");
    158             }
    159         }
    160     }
    161 
    162     return NULL;
    163 }
    164 
    165 }
    166 
    167 extern "C"
    168 {
    169 
    170 rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId)
    171 {
    172     rx::Renderer *renderer = NULL;
    173     EGLint status = EGL_BAD_ALLOC;
    174 
    175     if (ANGLE_ENABLE_D3D11 ||
    176         displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
    177         displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE)
    178     {
    179         renderer = new rx::Renderer11(display, hDc);
    180 
    181         if (renderer)
    182         {
    183             status = renderer->initialize();
    184         }
    185 
    186         if (status == EGL_SUCCESS)
    187         {
    188             return renderer;
    189         }
    190         else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE)
    191         {
    192             return NULL;
    193         }
    194 
    195         // Failed to create a D3D11 renderer, try creating a D3D9 renderer
    196         delete renderer;
    197     }
    198 
    199     bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE);
    200     renderer = new rx::Renderer9(display, hDc, softwareDevice);
    201 
    202     if (renderer)
    203     {
    204         status = renderer->initialize();
    205     }
    206 
    207     if (status == EGL_SUCCESS)
    208     {
    209         return renderer;
    210     }
    211 
    212     return NULL;
    213 }
    214 
    215 void glDestroyRenderer(rx::Renderer *renderer)
    216 {
    217     delete renderer;
    218 }
    219 
    220 }