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 }