1 2 // Copyright 2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // RendererD3D.h: Defines a back-end specific class for the DirectX renderer. 8 9 #ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ 10 #define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ 11 12 #include <array> 13 14 #include "common/Color.h" 15 #include "common/MemoryBuffer.h" 16 #include "common/debug.h" 17 #include "libANGLE/Device.h" 18 #include "libANGLE/State.h" 19 #include "libANGLE/Version.h" 20 #include "libANGLE/angletypes.h" 21 #include "libANGLE/formatutils.h" 22 #include "libANGLE/renderer/d3d/VertexDataManager.h" 23 #include "libANGLE/renderer/d3d/formatutilsD3D.h" 24 #include "libANGLE/renderer/renderer_utils.h" 25 #include "libANGLE/renderer/serial_utils.h" 26 #include "platform/FeaturesD3D.h" 27 28 namespace egl 29 { 30 class ConfigSet; 31 } 32 33 namespace gl 34 { 35 class ErrorSet; 36 class FramebufferState; 37 class InfoLog; 38 class Texture; 39 struct LinkedVarying; 40 } // namespace gl 41 42 namespace rx 43 { 44 class ContextImpl; 45 struct D3DUniform; 46 struct D3DVarying; 47 class DeviceD3D; 48 class EGLImageD3D; 49 class FramebufferImpl; 50 class ImageD3D; 51 class IndexBuffer; 52 class NativeWindowD3D; 53 class ProgramD3D; 54 class RenderTargetD3D; 55 class ShaderExecutableD3D; 56 class SwapChainD3D; 57 class TextureStorage; 58 struct TranslatedIndexData; 59 class UniformStorageD3D; 60 class VertexBuffer; 61 62 struct DeviceIdentifier 63 { 64 UINT VendorId; 65 UINT DeviceId; 66 UINT SubSysId; 67 UINT Revision; 68 UINT FeatureLevel; 69 }; 70 71 enum RendererClass 72 { 73 RENDERER_D3D11, 74 RENDERER_D3D9 75 }; 76 77 // A d3d::Context wraps error handling. 78 namespace d3d 79 { 80 class Context : angle::NonCopyable 81 { 82 public: Context()83 Context() {} ~Context()84 virtual ~Context() {} 85 86 virtual void handleResult(HRESULT hr, 87 const char *message, 88 const char *file, 89 const char *function, 90 unsigned int line) = 0; 91 }; 92 } // namespace d3d 93 94 // ANGLE_TRY for HRESULT errors. 95 #define ANGLE_TRY_HR(CONTEXT, EXPR, MESSAGE) \ 96 do \ 97 { \ 98 auto ANGLE_LOCAL_VAR = (EXPR); \ 99 if (ANGLE_UNLIKELY(FAILED(ANGLE_LOCAL_VAR))) \ 100 { \ 101 CONTEXT->handleResult(ANGLE_LOCAL_VAR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \ 102 return angle::Result::Stop; \ 103 } \ 104 } while (0) 105 106 #define ANGLE_CHECK_HR(CONTEXT, EXPR, MESSAGE, ERROR) \ 107 do \ 108 { \ 109 if (ANGLE_UNLIKELY(!(EXPR))) \ 110 { \ 111 CONTEXT->handleResult(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \ 112 return angle::Result::Stop; \ 113 } \ 114 } while (0) 115 116 #define ANGLE_HR_UNREACHABLE(context) \ 117 UNREACHABLE(); \ 118 ANGLE_CHECK_HR(context, false, "Unreachble code reached.", E_FAIL) 119 120 // Check if the device is lost every 10 failures to get the query data 121 constexpr unsigned int kPollingD3DDeviceLostCheckFrequency = 10; 122 123 // Useful for unit testing 124 class BufferFactoryD3D : angle::NonCopyable 125 { 126 public: BufferFactoryD3D()127 BufferFactoryD3D() {} ~BufferFactoryD3D()128 virtual ~BufferFactoryD3D() {} 129 130 virtual VertexBuffer *createVertexBuffer() = 0; 131 virtual IndexBuffer *createIndexBuffer() = 0; 132 133 // TODO(jmadill): add VertexFormatCaps 134 virtual VertexConversionType getVertexConversionType(angle::FormatID vertexFormatID) const = 0; 135 virtual GLenum getVertexComponentType(angle::FormatID vertexFormatID) const = 0; 136 137 // Warning: you should ensure binding really matches attrib.bindingIndex before using this 138 // function. 139 virtual angle::Result getVertexSpaceRequired(const gl::Context *context, 140 const gl::VertexAttribute &attrib, 141 const gl::VertexBinding &binding, 142 size_t count, 143 GLsizei instances, 144 unsigned int *bytesRequiredOut) const = 0; 145 }; 146 147 using AttribIndexArray = gl::AttribArray<int>; 148 149 class RendererD3D : public BufferFactoryD3D 150 { 151 public: 152 explicit RendererD3D(egl::Display *display); 153 ~RendererD3D() override; 154 155 virtual egl::Error initialize() = 0; 156 157 virtual egl::ConfigSet generateConfigs() = 0; 158 virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0; 159 160 virtual ContextImpl *createContext(const gl::State &state, gl::ErrorSet *errorSet) = 0; 161 162 std::string getVendorString() const; 163 164 virtual int getMinorShaderModel() const = 0; 165 virtual std::string getShaderModelSuffix() const = 0; 166 167 // Direct3D Specific methods 168 virtual DeviceIdentifier getAdapterIdentifier() const = 0; 169 170 virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0; 171 virtual NativeWindowD3D *createNativeWindow(EGLNativeWindowType window, 172 const egl::Config *config, 173 const egl::AttributeMap &attribs) const = 0; 174 175 virtual SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow, 176 HANDLE shareHandle, 177 IUnknown *d3dTexture, 178 GLenum backBufferFormat, 179 GLenum depthBufferFormat, 180 EGLint orientation, 181 EGLint samples) = 0; 182 virtual egl::Error getD3DTextureInfo(const egl::Config *configuration, 183 IUnknown *d3dTexture, 184 const egl::AttributeMap &attribs, 185 EGLint *width, 186 EGLint *height, 187 GLsizei *samples, 188 gl::Format *glFormat, 189 const angle::Format **angleFormat) const = 0; 190 virtual egl::Error validateShareHandle(const egl::Config *config, 191 HANDLE shareHandle, 192 const egl::AttributeMap &attribs) const = 0; 193 194 virtual int getMajorShaderModel() const = 0; 195 196 const angle::FeaturesD3D &getFeatures() const; 197 198 // Pixel operations 199 virtual angle::Result copyImage2D(const gl::Context *context, 200 const gl::Framebuffer *framebuffer, 201 const gl::Rectangle &sourceRect, 202 GLenum destFormat, 203 const gl::Offset &destOffset, 204 TextureStorage *storage, 205 GLint level) = 0; 206 virtual angle::Result copyImageCube(const gl::Context *context, 207 const gl::Framebuffer *framebuffer, 208 const gl::Rectangle &sourceRect, 209 GLenum destFormat, 210 const gl::Offset &destOffset, 211 TextureStorage *storage, 212 gl::TextureTarget target, 213 GLint level) = 0; 214 virtual angle::Result copyImage3D(const gl::Context *context, 215 const gl::Framebuffer *framebuffer, 216 const gl::Rectangle &sourceRect, 217 GLenum destFormat, 218 const gl::Offset &destOffset, 219 TextureStorage *storage, 220 GLint level) = 0; 221 virtual angle::Result copyImage2DArray(const gl::Context *context, 222 const gl::Framebuffer *framebuffer, 223 const gl::Rectangle &sourceRect, 224 GLenum destFormat, 225 const gl::Offset &destOffset, 226 TextureStorage *storage, 227 GLint level) = 0; 228 229 virtual angle::Result copyTexture(const gl::Context *context, 230 const gl::Texture *source, 231 GLint sourceLevel, 232 gl::TextureTarget srcTarget, 233 const gl::Box &sourceBox, 234 GLenum destFormat, 235 GLenum destType, 236 const gl::Offset &destOffset, 237 TextureStorage *storage, 238 gl::TextureTarget destTarget, 239 GLint destLevel, 240 bool unpackFlipY, 241 bool unpackPremultiplyAlpha, 242 bool unpackUnmultiplyAlpha) = 0; 243 virtual angle::Result copyCompressedTexture(const gl::Context *context, 244 const gl::Texture *source, 245 GLint sourceLevel, 246 TextureStorage *storage, 247 GLint destLevel) = 0; 248 249 // RenderTarget creation 250 virtual angle::Result createRenderTarget(const gl::Context *context, 251 int width, 252 int height, 253 GLenum format, 254 GLsizei samples, 255 RenderTargetD3D **outRT) = 0; 256 virtual angle::Result createRenderTargetCopy(const gl::Context *context, 257 RenderTargetD3D *source, 258 RenderTargetD3D **outRT) = 0; 259 260 // Shader operations 261 virtual angle::Result loadExecutable(d3d::Context *context, 262 const uint8_t *function, 263 size_t length, 264 gl::ShaderType type, 265 const std::vector<D3DVarying> &streamOutVaryings, 266 bool separatedOutputBuffers, 267 ShaderExecutableD3D **outExecutable) = 0; 268 virtual angle::Result compileToExecutable(d3d::Context *context, 269 gl::InfoLog &infoLog, 270 const std::string &shaderHLSL, 271 gl::ShaderType type, 272 const std::vector<D3DVarying> &streamOutVaryings, 273 bool separatedOutputBuffers, 274 const angle::CompilerWorkaroundsD3D &workarounds, 275 ShaderExecutableD3D **outExectuable) = 0; 276 virtual angle::Result ensureHLSLCompilerInitialized(d3d::Context *context) = 0; 277 278 virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0; 279 280 // Image operations 281 virtual ImageD3D *createImage() = 0; 282 virtual ExternalImageSiblingImpl *createExternalImageSibling( 283 const gl::Context *context, 284 EGLenum target, 285 EGLClientBuffer buffer, 286 const egl::AttributeMap &attribs) = 0; 287 virtual angle::Result generateMipmap(const gl::Context *context, 288 ImageD3D *dest, 289 ImageD3D *source) = 0; 290 virtual angle::Result generateMipmapUsingD3D(const gl::Context *context, 291 TextureStorage *storage, 292 const gl::TextureState &textureState) = 0; 293 virtual angle::Result copyImage(const gl::Context *context, 294 ImageD3D *dest, 295 ImageD3D *source, 296 const gl::Box &sourceBox, 297 const gl::Offset &destOffset, 298 bool unpackFlipY, 299 bool unpackPremultiplyAlpha, 300 bool unpackUnmultiplyAlpha) = 0; 301 virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0; 302 virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage, 303 RenderTargetD3D *renderTargetD3D) = 0; 304 virtual TextureStorage *createTextureStorageExternal( 305 egl::Stream *stream, 306 const egl::Stream::GLTextureDescription &desc) = 0; 307 virtual TextureStorage *createTextureStorage2D(GLenum internalformat, 308 bool renderTarget, 309 GLsizei width, 310 GLsizei height, 311 int levels, 312 bool hintLevelZeroOnly) = 0; 313 virtual TextureStorage *createTextureStorageCube(GLenum internalformat, 314 bool renderTarget, 315 int size, 316 int levels, 317 bool hintLevelZeroOnly) = 0; 318 virtual TextureStorage *createTextureStorage3D(GLenum internalformat, 319 bool renderTarget, 320 GLsizei width, 321 GLsizei height, 322 GLsizei depth, 323 int levels) = 0; 324 virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, 325 bool renderTarget, 326 GLsizei width, 327 GLsizei height, 328 GLsizei depth, 329 int levels) = 0; 330 virtual TextureStorage *createTextureStorage2DMultisample(GLenum internalformat, 331 GLsizei width, 332 GLsizei height, 333 int levels, 334 int samples, 335 bool fixedSampleLocations) = 0; 336 virtual TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat, 337 GLsizei width, 338 GLsizei height, 339 GLsizei depth, 340 int levels, 341 int samples, 342 bool fixedSampleLocations) = 0; 343 344 // Buffer-to-texture and Texture-to-buffer copies 345 virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; 346 virtual angle::Result fastCopyBufferToTexture(const gl::Context *context, 347 const gl::PixelUnpackState &unpack, 348 gl::Buffer *unpackBuffer, 349 unsigned int offset, 350 RenderTargetD3D *destRenderTarget, 351 GLenum destinationFormat, 352 GLenum sourcePixelsType, 353 const gl::Box &destArea) = 0; 354 355 // Device lost 356 gl::GraphicsResetStatus getResetStatus(); 357 void notifyDeviceLost(); 358 virtual bool resetDevice() = 0; 359 virtual bool testDeviceLost() = 0; 360 virtual bool testDeviceResettable() = 0; 361 362 virtual RendererClass getRendererClass() const = 0; 363 virtual void *getD3DDevice() = 0; 364 365 void setGPUDisjoint(); 366 367 GLint getGPUDisjoint(); 368 GLint64 getTimestamp(); 369 370 virtual angle::Result clearRenderTarget(const gl::Context *context, 371 RenderTargetD3D *renderTarget, 372 const gl::ColorF &clearColorValue, 373 const float clearDepthValue, 374 const unsigned int clearStencilValue) = 0; 375 376 virtual DeviceImpl *createEGLDevice() = 0; 377 presentPathFastEnabled()378 bool presentPathFastEnabled() const { return mPresentPathFastEnabled; } 379 380 // Stream creation 381 virtual StreamProducerImpl *createStreamProducerD3DTexture( 382 egl::Stream::ConsumerType consumerType, 383 const egl::AttributeMap &attribs) = 0; 384 385 const gl::Caps &getNativeCaps() const; 386 const gl::TextureCapsMap &getNativeTextureCaps() const; 387 const gl::Extensions &getNativeExtensions() const; 388 const gl::Limitations &getNativeLimitations() const; 389 390 // Necessary hack for default framebuffers in D3D. 391 virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0; 392 393 virtual gl::Version getMaxSupportedESVersion() const = 0; 394 virtual gl::Version getMaxConformantESVersion() const = 0; 395 396 angle::Result initRenderTarget(const gl::Context *context, RenderTargetD3D *renderTarget); 397 398 virtual angle::Result getIncompleteTexture(const gl::Context *context, 399 gl::TextureType type, 400 gl::Texture **textureOut) = 0; 401 402 Serial generateSerial(); 403 404 virtual bool canSelectViewInVertexShader() const = 0; 405 406 protected: 407 virtual bool getLUID(LUID *adapterLuid) const = 0; 408 virtual void generateCaps(gl::Caps *outCaps, 409 gl::TextureCapsMap *outTextureCaps, 410 gl::Extensions *outExtensions, 411 gl::Limitations *outLimitations) const = 0; 412 413 bool skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode); 414 415 egl::Display *mDisplay; 416 417 bool mPresentPathFastEnabled; 418 419 private: 420 void ensureCapsInitialized() const; 421 422 virtual void initializeFeatures(angle::FeaturesD3D *features) const = 0; 423 424 mutable bool mCapsInitialized; 425 mutable gl::Caps mNativeCaps; 426 mutable gl::TextureCapsMap mNativeTextureCaps; 427 mutable gl::Extensions mNativeExtensions; 428 mutable gl::Limitations mNativeLimitations; 429 430 mutable bool mFeaturesInitialized; 431 mutable angle::FeaturesD3D mFeatures; 432 433 bool mDisjoint; 434 bool mDeviceLost; 435 436 SerialFactory mSerialFactory; 437 }; 438 439 unsigned int GetBlendSampleMask(const gl::State &glState, int samples); 440 bool InstancedPointSpritesActive(ProgramD3D *programD3D, gl::PrimitiveMode mode); 441 GLenum DefaultGLErrorCode(HRESULT hr); 442 } // namespace rx 443 444 #endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ 445