| // | |
| // Copyright 2014 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. | |
| // | |
| // RendererD3D.cpp: Implementation of the base D3D Renderer. | |
| #include "libANGLE/renderer/d3d/RendererD3D.h" | |
| #include "common/MemoryBuffer.h" | |
| #include "common/debug.h" | |
| #include "common/utilities.h" | |
| #include "libANGLE/Context.h" | |
| #include "libANGLE/Display.h" | |
| #include "libANGLE/Framebuffer.h" | |
| #include "libANGLE/FramebufferAttachment.h" | |
| #include "libANGLE/ImageIndex.h" | |
| #include "libANGLE/ResourceManager.h" | |
| #include "libANGLE/State.h" | |
| #include "libANGLE/VertexArray.h" | |
| #include "libANGLE/formatutils.h" | |
| #include "libANGLE/renderer/ContextImpl.h" | |
| #include "libANGLE/renderer/TextureImpl.h" | |
| #include "libANGLE/renderer/d3d/BufferD3D.h" | |
| #include "libANGLE/renderer/d3d/DeviceD3D.h" | |
| #include "libANGLE/renderer/d3d/DisplayD3D.h" | |
| #include "libANGLE/renderer/d3d/IndexDataManager.h" | |
| #include "libANGLE/renderer/d3d/ProgramD3D.h" | |
| #include "libANGLE/renderer/d3d/SamplerD3D.h" | |
| #include "libANGLE/renderer/d3d/TextureD3D.h" | |
| namespace rx | |
| { | |
| RendererD3D::RendererD3D(egl::Display *display) | |
| : mDisplay(display), | |
| mPresentPathFastEnabled(false), | |
| mCapsInitialized(false), | |
| mFeaturesInitialized(false), | |
| mDisjoint(false), | |
| mDeviceLost(false) | |
| {} | |
| RendererD3D::~RendererD3D() {} | |
| bool RendererD3D::skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode) | |
| { | |
| if (drawMode == gl::PrimitiveMode::Points) | |
| { | |
| bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize(); | |
| // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, | |
| // which affects varying interpolation. Since the value of gl_PointSize is | |
| // undefined when not written, just skip drawing to avoid unexpected results. | |
| if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused()) | |
| { | |
| // Notify developers of risking undefined behavior. | |
| WARN() << "Point rendering without writing to gl_PointSize."; | |
| return true; | |
| } | |
| } | |
| else if (gl::IsTriangleMode(drawMode)) | |
| { | |
| if (glState.getRasterizerState().cullFace && | |
| glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack) | |
| { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| gl::GraphicsResetStatus RendererD3D::getResetStatus() | |
| { | |
| if (!mDeviceLost) | |
| { | |
| if (testDeviceLost()) | |
| { | |
| mDeviceLost = true; | |
| notifyDeviceLost(); | |
| return gl::GraphicsResetStatus::UnknownContextReset; | |
| } | |
| return gl::GraphicsResetStatus::NoError; | |
| } | |
| if (testDeviceResettable()) | |
| { | |
| return gl::GraphicsResetStatus::NoError; | |
| } | |
| return gl::GraphicsResetStatus::UnknownContextReset; | |
| } | |
| void RendererD3D::notifyDeviceLost() | |
| { | |
| mDisplay->notifyDeviceLost(); | |
| } | |
| std::string RendererD3D::getVendorString() const | |
| { | |
| LUID adapterLuid = {}; | |
| if (getLUID(&adapterLuid)) | |
| { | |
| char adapterLuidString[64]; | |
| sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", | |
| adapterLuid.HighPart, adapterLuid.LowPart); | |
| return std::string(adapterLuidString); | |
| } | |
| return std::string(""); | |
| } | |
| void RendererD3D::setGPUDisjoint() | |
| { | |
| mDisjoint = true; | |
| } | |
| GLint RendererD3D::getGPUDisjoint() | |
| { | |
| bool disjoint = mDisjoint; | |
| // Disjoint flag is cleared when read | |
| mDisjoint = false; | |
| return disjoint; | |
| } | |
| GLint64 RendererD3D::getTimestamp() | |
| { | |
| // D3D has no way to get an actual timestamp reliably so 0 is returned | |
| return 0; | |
| } | |
| void RendererD3D::ensureCapsInitialized() const | |
| { | |
| if (!mCapsInitialized) | |
| { | |
| generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations); | |
| mCapsInitialized = true; | |
| } | |
| } | |
| const gl::Caps &RendererD3D::getNativeCaps() const | |
| { | |
| ensureCapsInitialized(); | |
| return mNativeCaps; | |
| } | |
| const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const | |
| { | |
| ensureCapsInitialized(); | |
| return mNativeTextureCaps; | |
| } | |
| const gl::Extensions &RendererD3D::getNativeExtensions() const | |
| { | |
| ensureCapsInitialized(); | |
| return mNativeExtensions; | |
| } | |
| const gl::Limitations &RendererD3D::getNativeLimitations() const | |
| { | |
| ensureCapsInitialized(); | |
| return mNativeLimitations; | |
| } | |
| Serial RendererD3D::generateSerial() | |
| { | |
| return mSerialFactory.generate(); | |
| } | |
| bool InstancedPointSpritesActive(ProgramD3D *programD3D, gl::PrimitiveMode mode) | |
| { | |
| return programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation() && | |
| mode == gl::PrimitiveMode::Points; | |
| } | |
| angle::Result RendererD3D::initRenderTarget(const gl::Context *context, | |
| RenderTargetD3D *renderTarget) | |
| { | |
| return clearRenderTarget(context, renderTarget, gl::ColorF(0, 0, 0, 0), 1, 0); | |
| } | |
| const angle::FeaturesD3D &RendererD3D::getFeatures() const | |
| { | |
| if (!mFeaturesInitialized) | |
| { | |
| initializeFeatures(&mFeatures); | |
| mFeaturesInitialized = true; | |
| } | |
| return mFeatures; | |
| } | |
| unsigned int GetBlendSampleMask(const gl::State &glState, int samples) | |
| { | |
| unsigned int mask = 0; | |
| if (glState.isSampleCoverageEnabled()) | |
| { | |
| GLfloat coverageValue = glState.getSampleCoverageValue(); | |
| if (coverageValue != 0) | |
| { | |
| float threshold = 0.5f; | |
| for (int i = 0; i < samples; ++i) | |
| { | |
| mask <<= 1; | |
| if ((i + 1) * coverageValue >= threshold) | |
| { | |
| threshold += 1.0f; | |
| mask |= 1; | |
| } | |
| } | |
| } | |
| bool coverageInvert = glState.getSampleCoverageInvert(); | |
| if (coverageInvert) | |
| { | |
| mask = ~mask; | |
| } | |
| } | |
| else | |
| { | |
| mask = 0xFFFFFFFF; | |
| } | |
| if (glState.isSampleMaskEnabled()) | |
| { | |
| mask &= glState.getSampleMaskWord(0); | |
| } | |
| return mask; | |
| } | |
| GLenum DefaultGLErrorCode(HRESULT hr) | |
| { | |
| switch (hr) | |
| { | |
| #ifdef ANGLE_ENABLE_D3D9 | |
| case D3DERR_OUTOFVIDEOMEMORY: | |
| #endif | |
| case E_OUTOFMEMORY: | |
| return GL_OUT_OF_MEMORY; | |
| default: | |
| return GL_INVALID_OPERATION; | |
| } | |
| } | |
| } // namespace rx |