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