Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
{
    IDirect3DDevice9 *device = getDevice();

    D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
    int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);

    if (supportedSamples == -1)
    {
        error(GL_OUT_OF_MEMORY);

        return;
    }

    if (width > 0 && height > 0)
    {
        HRESULT result = device->CreateRenderTarget(width, height, requestedFormat, 
                                                    es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL);

        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
        {
            error(GL_OUT_OF_MEMORY);

            return;
        }

        ASSERT(SUCCEEDED(result));
    }

    mWidth = width;
    mHeight = height;
    mInternalFormat = format;
    mD3DFormat = requestedFormat;
    mSamples = supportedSamples;
}
示例#2
0
RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples)
{
    mRenderer = Renderer9::makeRenderer9(renderer);
    mRenderTarget = NULL;

    D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat, mRenderer);
    int supportedSamples = mRenderer->getNearestSupportedSamples(renderFormat, samples);

    if (supportedSamples == -1)
    {
        gl::error(GL_OUT_OF_MEMORY);

        return;
    }

    HRESULT result = D3DERR_INVALIDCALL;

    GLuint clientVersion = mRenderer->getCurrentClientVersion();

    if (width > 0 && height > 0)
    {
        IDirect3DDevice9 *device = mRenderer->getDevice();

        bool requiresInitialization = false;

        if (gl::GetDepthBits(internalFormat, clientVersion) > 0 ||
            gl::GetStencilBits(internalFormat, clientVersion) > 0)
        {
            result = device->CreateDepthStencilSurface(width, height, renderFormat,
                                                       gl_d3d9::GetMultisampleType(supportedSamples),
                                                       0, FALSE, &mRenderTarget, NULL);
        }
        else
        {
            requiresInitialization = gl_d3d9::RequiresTextureDataInitialization(internalFormat);

            result = device->CreateRenderTarget(width, height, renderFormat,
                                                gl_d3d9::GetMultisampleType(supportedSamples),
                                                0, FALSE, &mRenderTarget, NULL);
        }

        if (result == D3DERR_OUTOFVIDEOMEMORY ||
            result == E_INVALIDARG ||
            result == E_OUTOFMEMORY)
        {
            gl::error(GL_OUT_OF_MEMORY);

            return;
        }

        ASSERT(SUCCEEDED(result));

        if (requiresInitialization)
        {
            // This format requires that the data be initialized before the render target can be used
            // Unfortunately this requires a Get call on the d3d device but it is far better than having
            // to mark the render target as lockable and copy data to the gpu.
            IDirect3DSurface9 *prevRenderTarget = NULL;
            device->GetRenderTarget(0, &prevRenderTarget);
            device->SetRenderTarget(0, mRenderTarget);
            device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
            device->SetRenderTarget(0, prevRenderTarget);
        }
    }

    mWidth = width;
    mHeight = height;
    mDepth = 1;
    mInternalFormat = internalFormat;
    mSamples = supportedSamples;
    mActualFormat = d3d9_gl::GetInternalFormat(renderFormat);
}
示例#3
0
bool Texture2D::Create()
{
    Release();

    if (!graphics_ || !width_ || !height_)
        return false;

    if (graphics_->IsDeviceLost())
    {
        URHO3D_LOGWARNING("Texture creation while device is lost");
        return true;
    }

    if (multiSample_ > 1 && !autoResolve_)
    {
        URHO3D_LOGWARNING("Multisampled texture without autoresolve is not supported on Direct3D9");
        autoResolve_ = true;
    }

    GraphicsImpl* impl = graphics_->GetImpl();

    unsigned pool = usage_ > TEXTURE_STATIC ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
    unsigned d3dUsage = 0;

    switch (usage_)
    {
    case TEXTURE_DYNAMIC:
        d3dUsage |= D3DUSAGE_DYNAMIC;
        break;
    case TEXTURE_RENDERTARGET:
        d3dUsage |= D3DUSAGE_RENDERTARGET;
        if (requestedLevels_ != 1)
        {
            // Check mipmap autogeneration support
            if (impl->CheckFormatSupport((D3DFORMAT)format_, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE))
            {
                requestedLevels_ = 0;
                d3dUsage |= D3DUSAGE_AUTOGENMIPMAP;
            }
            else
                requestedLevels_ = 1;
        }
        break;
    case TEXTURE_DEPTHSTENCIL:
        d3dUsage |= D3DUSAGE_DEPTHSTENCIL;
        // No mipmaps for depth-stencil textures
        requestedLevels_ = 1;
        break;
    default:
        break;
    }

    if (multiSample_ > 1)
    {
        // Fall back to non-multisampled if unsupported multisampling mode
        if (!impl->CheckMultiSampleSupport((D3DFORMAT)format_,  multiSample_))
        {
            multiSample_ = 1;
            autoResolve_ = false;
        }
    }

    IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
    // If creating a depth-stencil texture, and it is not supported, create a depth-stencil surface instead
    // Multisampled surfaces need also to be created this way
    if (usage_ == TEXTURE_DEPTHSTENCIL && (multiSample_ > 1 || !graphics_->GetImpl()->CheckFormatSupport((D3DFORMAT)format_, 
        d3dUsage, D3DRTYPE_TEXTURE)))
    {
        HRESULT hr = device->CreateDepthStencilSurface(
            (UINT)width_,
            (UINT)height_,
            (D3DFORMAT)format_,
            (multiSample_ > 1) ? (D3DMULTISAMPLE_TYPE)multiSample_ : D3DMULTISAMPLE_NONE,
            0,
            FALSE,
            (IDirect3DSurface9**)&renderSurface_->surface_,
            nullptr);
        if (FAILED(hr))
        {
            URHO3D_LOGD3DERROR("Could not create depth-stencil surface", hr);
            URHO3D_SAFE_RELEASE(renderSurface_->surface_);
            return false;
        }

        levels_ = 1;
    }
    else
    {
        HRESULT hr = graphics_->GetImpl()->GetDevice()->CreateTexture(
            (UINT)width_,
            (UINT)height_,
            requestedLevels_,
            d3dUsage,
            (D3DFORMAT)format_,
            (D3DPOOL)pool,
            (IDirect3DTexture9**)&object_,
            nullptr);
        if (FAILED(hr))
        {
            URHO3D_LOGD3DERROR("Could not create texture", hr);
            URHO3D_SAFE_RELEASE(object_.ptr_);
            return false;
        }

        levels_ = ((IDirect3DTexture9*)object_.ptr_)->GetLevelCount();

        // Create the multisampled rendertarget for rendering to if necessary
        if (usage_ == TEXTURE_RENDERTARGET && multiSample_ > 1)
        {
            HRESULT hr = device->CreateRenderTarget(
                (UINT)width_,
                (UINT)height_,
                (D3DFORMAT)format_,
                (D3DMULTISAMPLE_TYPE)multiSample_,
                0,
                FALSE,
                (IDirect3DSurface9**)&renderSurface_->surface_,
                nullptr);
            if (FAILED(hr))
            {
                URHO3D_LOGD3DERROR("Could not create multisampled rendertarget surface", hr);
                URHO3D_SAFE_RELEASE(renderSurface_->surface_);
                return false;
            }
        }
        else if (usage_ >= TEXTURE_RENDERTARGET)
        {
            // Else use the texture surface directly for rendering
            hr = ((IDirect3DTexture9*)object_.ptr_)->GetSurfaceLevel(0, (IDirect3DSurface9**)&renderSurface_->surface_);
            if (FAILED(hr))
            {
                URHO3D_LOGD3DERROR("Could not get rendertarget surface", hr);
                URHO3D_SAFE_RELEASE(renderSurface_->surface_);
                return false;
            }
        }
    }

    return true;
}
示例#4
0
bool TextureCube::Create()
{
    Release();

    if (!graphics_ || !width_ || !height_)
        return false;

    if (graphics_->IsDeviceLost())
    {
        URHO3D_LOGWARNING("Texture creation while device is lost");
        return true;
    }

    GraphicsImpl* impl = graphics_->GetImpl();

    unsigned pool = usage_ > TEXTURE_STATIC ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
    unsigned d3dUsage = 0;

    switch (usage_)
    {
    case TEXTURE_DYNAMIC:
        d3dUsage |= D3DUSAGE_DYNAMIC;
        break;
    case TEXTURE_RENDERTARGET:
        d3dUsage |= D3DUSAGE_RENDERTARGET;
        if (requestedLevels_ != 1)
        {
            // Check mipmap autogeneration support
            if (impl->CheckFormatSupport((D3DFORMAT)format_, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE))
            {
                requestedLevels_ = 0;
                d3dUsage |= D3DUSAGE_AUTOGENMIPMAP;
            }
            else
                requestedLevels_ = 1;
        }
        break;
    default:
        break;
    }

    if (multiSample_ > 1)
    {
        // Fall back to non-multisampled if unsupported multisampling mode
        GraphicsImpl* impl = graphics_->GetImpl();
        if (!impl->CheckMultiSampleSupport((D3DFORMAT)format_, multiSample_))
        {
            multiSample_ = 1;
            autoResolve_ = false;
        }
    }

    IDirect3DDevice9* device = graphics_->GetImpl()->GetDevice();
    HRESULT hr = device->CreateCubeTexture(
        (UINT)width_,
        requestedLevels_,
        d3dUsage,
        (D3DFORMAT)format_,
        (D3DPOOL)pool,
        (IDirect3DCubeTexture9**)&object_.ptr_,
        nullptr);
    if (FAILED(hr))
    {
        URHO3D_LOGD3DERROR("Could not create cube texture", hr);
        URHO3D_SAFE_RELEASE(object_.ptr_);
        return false;
    }

    levels_ = ((IDirect3DCubeTexture9*)object_.ptr_)->GetLevelCount();

    if (usage_ == TEXTURE_RENDERTARGET)
    {
        for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
        {
            if (multiSample_ > 1)
            {
                // Create the multisampled face rendertarget if necessary
                HRESULT hr = device->CreateRenderTarget(
                    (UINT)width_,
                    (UINT)height_,
                    (D3DFORMAT)format_,
                    (D3DMULTISAMPLE_TYPE)multiSample_,
                    0,
                    FALSE,
                    (IDirect3DSurface9**)&renderSurfaces_[i]->surface_,
                    nullptr);
                if (FAILED(hr))
                {
                    URHO3D_LOGD3DERROR("Could not create multisampled rendertarget surface", hr);
                    URHO3D_SAFE_RELEASE(renderSurfaces_[i]->surface_);
                    return false;
                }
            }
            else
            {
                hr = ((IDirect3DCubeTexture9*)object_.ptr_)->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0,
                    (IDirect3DSurface9**)&renderSurfaces_[i]->surface_);
                if (FAILED(hr))
                {
                    URHO3D_LOGD3DERROR("Could not get rendertarget surface", hr);
                    URHO3D_SAFE_RELEASE(renderSurfaces_[i]->surface_);
                    return false;
                }
            }
        }
    }

    return true;
}
示例#5
0
HRESULT WINAPI D3D9SCPresent(IDirect3DSwapChain9 *pSc, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion, DWORD dwFlags) {

    D3D9FrameGrabber *d3d9FrameGrabber = D3D9FrameGrabber::getInstance();
    Logger *logger = d3d9FrameGrabber->m_logger;
    DWORD errorcode;
    if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(d3d9FrameGrabber->m_syncRunMutex, 0))) {
        IPCContext *ipcContext = d3d9FrameGrabber->m_ipcContext;
        logger->reportLogDebug(L"D3D9SCPresent");
        IDirect3DSurface9 *pBackBuffer = NULL;
        D3DPRESENT_PARAMETERS params;
        RECT newRect = RECT();
        IDirect3DSurface9 *pDemultisampledSurf = NULL;
        IDirect3DSurface9 *pOffscreenSurf = NULL;
        IDirect3DDevice9 *pDev = NULL;

        HRESULT hRes = pSc->GetPresentParameters(&params);

        if (FAILED(hRes) || params.Windowed) {
            goto end;
        }

        if (FAILED(hRes = pSc->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer))) {
            logger->reportLogError(L"d3d9sc couldn't get backbuffer. errorcode = 0x%x", hRes);
            goto end;
        }
        D3DSURFACE_DESC surfDesc;
        pBackBuffer->GetDesc(&surfDesc);

        hRes = pSc->GetDevice(&pDev);
        if (FAILED(hRes))
        {
            logger->reportLogError(L"GetFramePrep: FAILED to get pDev. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format );
            goto end;
        }
        hRes = pDev->CreateRenderTarget(
            surfDesc.Width, surfDesc.Height,
            surfDesc.Format, D3DMULTISAMPLE_NONE, 0, false,
            &pDemultisampledSurf, NULL );
        if (FAILED(hRes))
        {
            logger->reportLogError(L"GetFramePrep: FAILED to create demultisampled render target. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format );
            goto end;
        }

        hRes = pDev->StretchRect(pBackBuffer, NULL, pDemultisampledSurf, NULL, D3DTEXF_LINEAR );
        if (FAILED(hRes))
        {
            logger->reportLogError(L"GetFramePrep: StretchRect FAILED for image surfacee. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format );
            goto end;
        }

        hRes = pDev->CreateOffscreenPlainSurface(
            surfDesc.Width, surfDesc.Height,
            surfDesc.Format, D3DPOOL_SYSTEMMEM,
            &pOffscreenSurf, NULL );
        if (FAILED(hRes))
        {
            logger->reportLogError(L"GetFramePrep: FAILED to create image surface. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format );
            goto end;
        }

        hRes = pDev->GetRenderTargetData(pDemultisampledSurf, pOffscreenSurf );
        if (FAILED(hRes))
        {
            logger->reportLogError(L"GetFramePrep: GetRenderTargetData() FAILED for image surfacee. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format );
            goto end;
        }

        D3DLOCKED_RECT lockedSrcRect;
        newRect.right = surfDesc.Width;
        newRect.bottom = surfDesc.Height;

        hRes = pOffscreenSurf->LockRect( &lockedSrcRect, &newRect, 0);
        if (FAILED(hRes))
        {
            logger->reportLogError(L"GetFramePrep: FAILED to lock source rect. (0x%x)", hRes );
            goto end;
        }

        ipcContext->m_memDesc.width = surfDesc.Width;
        ipcContext->m_memDesc.height = surfDesc.Height;
        ipcContext->m_memDesc.rowPitch = lockedSrcRect.Pitch;
        ipcContext->m_memDesc.frameId++;
        ipcContext->m_memDesc.format = getCompatibleBufferFormat(surfDesc.Format);

        if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(ipcContext->m_hMutex, 0))) {
            //            __asm__("int $3");
    //        reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d9sc writing description to mem mapped file");
            memcpy(ipcContext->m_pMemMap, &ipcContext->m_memDesc, sizeof (ipcContext->m_memDesc));
    //        reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d9sc writing data to mem mapped file");
            PVOID pMemDataMap = incPtr(ipcContext->m_pMemMap, sizeof (ipcContext->m_memDesc));
            if (static_cast<UINT>(lockedSrcRect.Pitch) == surfDesc.Width * 4) {
                memcpy(pMemDataMap, lockedSrcRect.pBits, surfDesc.Width * surfDesc.Height * 4);
            } else {
                UINT i = 0, cleanOffset = 0, pitchOffset = 0;
                while (i < surfDesc.Height) {
                    memcpy(incPtr(pMemDataMap, cleanOffset), incPtr(lockedSrcRect.pBits, pitchOffset), surfDesc.Width * 4);
                    cleanOffset += surfDesc.Width * 4;
                    pitchOffset += lockedSrcRect.Pitch;
                    i++;
                }
            }
            ReleaseMutex(ipcContext->m_hMutex);
            SetEvent(ipcContext->m_hFrameGrabbedEvent);
        } else {
            logger->reportLogError(L"d3d9sc couldn't wait mutex. errocode = 0x%x", errorcode);
        }
end:
        if(pOffscreenSurf) pOffscreenSurf->Release();
        if(pDemultisampledSurf) pDemultisampledSurf->Release();
        if(pBackBuffer) pBackBuffer->Release();
        if(pDev) pDev->Release();

        ProxyFuncJmp *d3d9SCPresentProxyFuncJmp = d3d9FrameGrabber->m_d3d9SCPresentProxyFuncJmp;

        if(d3d9SCPresentProxyFuncJmp->removeHook()) {
            int i = GetLastError();
            logger->reportLogError(L"d3d9sc error occured while trying to removeHook before original call0x%x", i);
        }
        HRESULT result = pSc->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);

        if(d3d9SCPresentProxyFuncJmp->installHook()) {
            int i = GetLastError();
            logger->reportLogError(L"d3d9sc error occured while trying to installHook after original call0x%x", i);
        }

        ReleaseMutex(d3d9FrameGrabber->m_syncRunMutex);

        return result;
    } else {
        logger->reportLogError(L"d3d9sc present is skipped because mutex is busy");
        return S_FALSE;
    }
}
示例#6
0
void Surface::resetSwapChain()
{
    IDirect3DDevice9 *device = mDisplay->getDevice();

    D3DPRESENT_PARAMETERS presentParameters = {0};

    presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
    presentParameters.BackBufferCount = 1;
    presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat;
    presentParameters.EnableAutoDepthStencil = FALSE;
    presentParameters.Flags = 0;
    presentParameters.hDeviceWindow = getWindowHandle();
    presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
    presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
    presentParameters.PresentationInterval = Display::convertInterval(mConfig->mMinSwapInterval);
    presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
    presentParameters.Windowed = TRUE;

    RECT windowRect;
    if (!GetClientRect(getWindowHandle(), &windowRect))
    {
        ASSERT(false);
        return;
    }

    presentParameters.BackBufferWidth = windowRect.right - windowRect.left;
    presentParameters.BackBufferHeight = windowRect.bottom - windowRect.top;

    IDirect3DSwapChain9 *swapChain = NULL;
    HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &swapChain);

    if (FAILED(result))
    {
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

        ERR("Could not create additional swap chains: %08lX", result);
        return error(EGL_BAD_ALLOC);
    }

    IDirect3DSurface9 *depthStencilSurface = NULL;
    result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
                                               presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
                                               presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL);

    if (FAILED(result))
    {
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

        swapChain->Release();

        ERR("Could not create depthstencil surface for new swap chain: %08lX", result);
        return error(EGL_BAD_ALLOC);
    }

    IDirect3DSurface9 *renderTarget = NULL;
    result = device->CreateRenderTarget(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.BackBufferFormat,
                                        presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &renderTarget, NULL);

    if (FAILED(result))
    {
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

        swapChain->Release();
        depthStencilSurface->Release();

        ERR("Could not create render target surface for new swap chain: %08lX", result);
        return error(EGL_BAD_ALLOC);
    }

    ASSERT(SUCCEEDED(result));

    IDirect3DTexture9 *flipTexture = NULL;
    result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
                                   presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &flipTexture, NULL);

    if (FAILED(result))
    {
        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);

        swapChain->Release();
        depthStencilSurface->Release();
        renderTarget->Release();

        ERR("Could not create flip texture for new swap chain: %08lX", result);
        return error(EGL_BAD_ALLOC);
    }

    IDirect3DSurface9 *backBuffer = NULL;
    swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);

    if (mSwapChain) mSwapChain->Release();
    if (mDepthStencil) mDepthStencil->Release();
    if (mBackBuffer) mBackBuffer->Release();
    if (mRenderTarget) mRenderTarget->Release();
    if (mFlipTexture) mFlipTexture->Release();

    mWidth = presentParameters.BackBufferWidth;
    mHeight = presentParameters.BackBufferHeight;

    mSwapChain = swapChain;
    mDepthStencil = depthStencilSurface;
    mBackBuffer = backBuffer;
    mRenderTarget = renderTarget;
    mFlipTexture = flipTexture;

    // The flip state block recorded mFlipTexture so it is now invalid.
    releaseRecordedState(device);
}