0N/A/*
2362N/A * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
430N/A#include "D3DPipeline.h"
0N/A#include "jlong.h"
0N/A
0N/A#include "GraphicsPrimitiveMgr.h"
430N/A#include "D3DContext.h"
0N/A#include "D3DSurfaceData.h"
430N/A#include "D3DBufImgOps.h"
430N/A#include "D3DPaints.h"
430N/A#include "D3DRenderQueue.h"
430N/A#include "D3DShaders.h"
430N/A#include "D3DTextRenderer.h"
430N/A#include "D3DPipelineManager.h"
430N/A#include "D3DGlyphCache.h"
0N/A
0N/Atypedef struct {
0N/A D3DBLEND src;
0N/A D3DBLEND dst;
0N/A} D3DBlendRule;
0N/A
0N/A/**
0N/A * This table contains the standard blending rules (or Porter-Duff compositing
0N/A * factors) used in SetRenderState(), indexed by the rule constants from the
0N/A * AlphaComposite class.
0N/A */
0N/AD3DBlendRule StdBlendRules[] = {
0N/A { D3DBLEND_ZERO, D3DBLEND_ZERO }, /* 0 - Nothing */
0N/A { D3DBLEND_ZERO, D3DBLEND_ZERO }, /* 1 - RULE_Clear */
0N/A { D3DBLEND_ONE, D3DBLEND_ZERO }, /* 2 - RULE_Src */
0N/A { D3DBLEND_ONE, D3DBLEND_INVSRCALPHA }, /* 3 - RULE_SrcOver */
0N/A { D3DBLEND_INVDESTALPHA, D3DBLEND_ONE }, /* 4 - RULE_DstOver */
0N/A { D3DBLEND_DESTALPHA, D3DBLEND_ZERO }, /* 5 - RULE_SrcIn */
0N/A { D3DBLEND_ZERO, D3DBLEND_SRCALPHA }, /* 6 - RULE_DstIn */
0N/A { D3DBLEND_INVDESTALPHA, D3DBLEND_ZERO }, /* 7 - RULE_SrcOut */
0N/A { D3DBLEND_ZERO, D3DBLEND_INVSRCALPHA }, /* 8 - RULE_DstOut */
0N/A { D3DBLEND_ZERO, D3DBLEND_ONE }, /* 9 - RULE_Dst */
0N/A { D3DBLEND_DESTALPHA, D3DBLEND_INVSRCALPHA }, /*10 - RULE_SrcAtop */
0N/A { D3DBLEND_INVDESTALPHA, D3DBLEND_SRCALPHA }, /*11 - RULE_DstAtop */
0N/A { D3DBLEND_INVDESTALPHA, D3DBLEND_INVSRCALPHA }, /*12 - RULE_AlphaXor*/
0N/A};
0N/A
430N/Avoid
430N/AD3DUtils_SetOrthoMatrixOffCenterLH(D3DMATRIX *m,
430N/A float width, float height)
430N/A{
430N/A ZeroMemory(m, sizeof(D3DMATRIX));
430N/A m->_11 = 2.0f/width;
430N/A m->_22 = -2.0f/height;
430N/A m->_33 = 0.5f;
430N/A m->_44 = 1.0f;
430N/A
430N/A m->_41 = -1.0f;
430N/A m->_42 = 1.0f;
430N/A m->_43 = 0.5f;
430N/A}
430N/A
430N/Avoid
430N/AD3DUtils_SetIdentityMatrix(D3DMATRIX *m)
0N/A{
430N/A m->_12 = m->_13 = m->_14 = m->_21 = m->_23 = m->_24 = 0.0f;
430N/A m->_31 = m->_32 = m->_34 = m->_41 = m->_42 = m->_43 = 0.0f;
430N/A m->_11 = m->_22 = m->_33 = m->_44 = 1.0f;
430N/A}
430N/A
430N/A// the following methods are copies of the AffineTransform's class
430N/A// corresponding methods, with these changes to the indexes:
430N/A// 00 -> 11
430N/A// 11 -> 22
430N/A// 01 -> 21
430N/A// 10 -> 12
430N/A// 02 -> 41
430N/A// 12 -> 42
430N/A
430N/Avoid
430N/AD3DUtils_2DConcatenateM(D3DMATRIX *m, D3DMATRIX *m1)
430N/A{
430N/A float M0, M1;
430N/A float T00, T10, T01, T11;
430N/A float T02, T12;
430N/A
430N/A T00 = m1->_11; T01 = m1->_21; T02 = m1->_41;
430N/A T10 = m1->_12; T11 = m1->_22; T12 = m1->_42;
430N/A
430N/A M0 = m->_11;
430N/A M1 = m->_21;
430N/A m->_11 = T00 * M0 + T10 * M1;
430N/A m->_21 = T01 * M0 + T11 * M1;
430N/A m->_41 += T02 * M0 + T12 * M1;
430N/A
430N/A M0 = m->_12;
430N/A M1 = m->_22;
430N/A m->_12 = T00 * M0 + T10 * M1;
430N/A m->_22 = T01 * M0 + T11 * M1;
430N/A m->_42 += T02 * M0 + T12 * M1;
0N/A}
0N/A
430N/A#ifdef UPDATE_TX
430N/A
430N/Avoid
430N/AD3DUtils_2DScaleM(D3DMATRIX *m, float sx, float sy)
430N/A{
430N/A m->_11 *= sx;
430N/A m->_22 *= sy;
430N/A}
430N/A
430N/Avoid
430N/AD3DUtils_2DInvertM(D3DMATRIX *m)
0N/A{
430N/A float M11, M21, M41;
430N/A float M12, M22, M42;
430N/A float det;
0N/A
430N/A M11 = m->_11; M21 = m->_21; M41 = m->_41;
430N/A M12 = m->_12; M22 = m->_22; M42 = m->_42;
430N/A det = M11 * M22 - M21 * M12;
430N/A if (fabs(det) <= 0.0000000001f) {
430N/A memset(m, 0, sizeof(D3DMATRIX));
430N/A return;
430N/A }
430N/A m->_11 = M22 / det;
430N/A m->_12 = -M12 / det;
430N/A m->_21 = -M21 / det;
430N/A m->_22 = M11 / det;
430N/A m->_41 = (M21 * M42 - M22 * M41) / det;
430N/A m->_42 = (M12 * M41 - M11 * M42) / det;
430N/A}
0N/A
430N/Avoid
430N/AD3DUtils_2DTranslateM(D3DMATRIX *m, float tx, float ty)
430N/A{
430N/A m->_41 = tx * m->_11 + ty * m->_21 + m->_41;
430N/A m->_42 = tx * m->_12 + ty * m->_22 + m->_42;
430N/A}
430N/A
430N/Avoid
430N/AD3DUtils_2DTransformXY(D3DMATRIX *m, float *px, float *py)
430N/A{
430N/A float x = *px;
430N/A float y = *py;
430N/A
430N/A *px = x * m->_11 + y * m->_21 + m->_41;
430N/A *py = x * m->_12 + y * m->_22 + m->_42;
430N/A}
430N/A
430N/Avoid
430N/AD3DUtils_2DInverseTransformXY(D3DMATRIX *m, float *px, float *py)
430N/A{
430N/A float x = *px, y = *py;
430N/A
430N/A x -= m->_41;
430N/A y -= m->_42;
430N/A
430N/A float det = m->_11 * m->_22 - m->_21 * m->_12;
430N/A if (fabs(det) < 0.0000000001f) {
430N/A *px = 0.0f;
430N/A *py = 0.0f;
0N/A } else {
430N/A *px = (x * m->_22 - y * m->_21) / det;
430N/A *py = (y * m->_11 - x * m->_12) / det;
0N/A }
0N/A}
0N/A
430N/A#endif // UPDATE_TX
430N/A
430N/Astatic void
430N/AD3DContext_DisposeShader(jlong programID)
430N/A{
430N/A IDirect3DPixelShader9 *shader =
430N/A (IDirect3DPixelShader9 *)jlong_to_ptr(programID);
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext_DisposeShader");
430N/A
430N/A SAFE_RELEASE(shader);
430N/A}
430N/A
430N/A// static
430N/AHRESULT
430N/AD3DContext::CreateInstance(IDirect3D9 *pd3d9, UINT adapter, D3DContext **ppCtx)
430N/A{
430N/A HRESULT res;
430N/A *ppCtx = new D3DContext(pd3d9, adapter);
430N/A if (FAILED(res = (*ppCtx)->InitContext())) {
430N/A delete *ppCtx;
430N/A *ppCtx = NULL;
430N/A }
430N/A return res;
430N/A}
0N/A
430N/AD3DContext::D3DContext(IDirect3D9 *pd3d, UINT adapter)
430N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::D3DContext");
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE, " pd3d=0x%x", pd3d);
430N/A pd3dObject = pd3d;
430N/A pd3dDevice = NULL;
430N/A adapterOrdinal = adapter;
430N/A
430N/A pResourceMgr = NULL;
430N/A pMaskCache = NULL;
430N/A pVCacher = NULL;
430N/A
430N/A pSyncQuery = NULL;
430N/A pSyncRTRes = NULL;
430N/A pStateBlock = NULL;
0N/A
430N/A D3DC_INIT_SHADER_LIST(convolvePrograms, MAX_CONVOLVE);
430N/A D3DC_INIT_SHADER_LIST(rescalePrograms, MAX_RESCALE);
430N/A D3DC_INIT_SHADER_LIST(lookupPrograms, MAX_LOOKUP);
430N/A D3DC_INIT_SHADER_LIST(basicGradPrograms, 4);
430N/A D3DC_INIT_SHADER_LIST(linearGradPrograms, 8);
430N/A D3DC_INIT_SHADER_LIST(radialGradPrograms, 8);
430N/A
430N/A pLCDGlyphCache= NULL;
430N/A pGrayscaleGlyphCache= NULL;
430N/A lcdTextProgram = NULL;
430N/A aaPgramProgram = NULL;
430N/A
430N/A contextCaps = CAPS_EMPTY;
430N/A bBeginScenePending = FALSE;
430N/A
430N/A ZeroMemory(&devCaps, sizeof(D3DCAPS9));
430N/A ZeroMemory(&curParams, sizeof(curParams));
430N/A
430N/A extraAlpha = 1.0f;
0N/A}
0N/A
430N/Avoid D3DContext::ReleaseDefPoolResources()
430N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ReleaseDefPoolResources");
0N/A
430N/A EndScene();
0N/A
430N/A D3DPipelineManager::NotifyAdapterEventListeners(devCaps.AdapterOrdinal,
430N/A DEVICE_RESET);
0N/A
430N/A contextCaps = CAPS_EMPTY;
0N/A
430N/A SAFE_RELEASE(pSyncQuery);
430N/A SAFE_RELEASE(pStateBlock);
0N/A
430N/A if (pVCacher != NULL) {
430N/A pVCacher->ReleaseDefPoolResources();
430N/A }
430N/A if (pMaskCache != NULL) {
430N/A pMaskCache->ReleaseDefPoolResources();
430N/A }
430N/A if (pLCDGlyphCache != NULL) {
430N/A pLCDGlyphCache->ReleaseDefPoolResources();
0N/A }
430N/A if (pGrayscaleGlyphCache != NULL) {
430N/A pGrayscaleGlyphCache->ReleaseDefPoolResources();
430N/A }
430N/A if (pResourceMgr != NULL) {
430N/A if (pSyncRTRes != NULL) {
430N/A pResourceMgr->ReleaseResource(pSyncRTRes);
430N/A pSyncRTRes = NULL;
430N/A }
430N/A pResourceMgr->ReleaseDefPoolResources();
430N/A }
430N/A ZeroMemory(lastTexture, sizeof(lastTexture));
430N/A ZeroMemory(lastTextureColorState, sizeof(lastTextureColorState));
430N/A}
0N/A
430N/Avoid D3DContext::ReleaseContextResources()
430N/A{
430N/A J2dTraceLn1(J2D_TRACE_INFO,
430N/A "D3DContext::ReleaseContextResources: pd3dDevice = 0x%x",
430N/A pd3dDevice);
430N/A
430N/A ReleaseDefPoolResources();
430N/A
430N/A D3DPipelineManager::NotifyAdapterEventListeners(devCaps.AdapterOrdinal,
430N/A DEVICE_DISPOSED);
430N/A
430N/A // dispose shader lists
430N/A ShaderList_Dispose(&convolvePrograms);
430N/A ShaderList_Dispose(&rescalePrograms);
430N/A ShaderList_Dispose(&lookupPrograms);
430N/A ShaderList_Dispose(&basicGradPrograms);
430N/A ShaderList_Dispose(&linearGradPrograms);
430N/A ShaderList_Dispose(&radialGradPrograms);
430N/A
430N/A SAFE_DELETE(pLCDGlyphCache);
430N/A SAFE_DELETE(pGrayscaleGlyphCache);
430N/A
430N/A SAFE_RELEASE(lcdTextProgram);
430N/A SAFE_RELEASE(aaPgramProgram);
430N/A
430N/A SAFE_DELETE(pVCacher);
430N/A SAFE_DELETE(pMaskCache);
430N/A SAFE_DELETE(pResourceMgr);
0N/A}
0N/A
0N/AD3DContext::~D3DContext() {
0N/A J2dTraceLn2(J2D_TRACE_INFO,
430N/A "~D3DContext: pd3dDevice=0x%x, pd3dObject =0x%x",
430N/A pd3dDevice, pd3dObject);
430N/A ReleaseContextResources();
430N/A SAFE_RELEASE(pd3dDevice);
0N/A}
0N/A
0N/AHRESULT
430N/AD3DContext::InitDevice(IDirect3DDevice9 *pd3dDevice)
0N/A{
430N/A HRESULT res = S_OK;
430N/A
430N/A pd3dDevice->GetDeviceCaps(&devCaps);
430N/A
0N/A J2dRlsTraceLn1(J2D_TRACE_INFO,
430N/A "D3DContext::InitDevice: device %d", adapterOrdinal);
0N/A
0N/A // disable some of the unneeded and costly d3d functionality
430N/A pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
430N/A pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
430N/A pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
430N/A pd3dDevice->SetRenderState(D3DRS_CLIPPING, FALSE);
430N/A pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
430N/A pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE);
430N/A pd3dDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE);
430N/A pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
0N/A
430N/A // set the default texture addressing mode
430N/A pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
430N/A pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
430N/A
430N/A // REMIND: check supported filters with
430N/A // IDirect3D9::CheckDeviceFormat with D3DUSAGE_QUERY_FILTER
430N/A pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
430N/A pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
0N/A
0N/A // these states never change
430N/A pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
430N/A pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
430N/A pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
430N/A pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
430N/A pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
430N/A pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
430N/A pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
430N/A pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
430N/A
0N/A // init the array of latest textures
430N/A ZeroMemory(lastTexture, sizeof(lastTexture));
430N/A ZeroMemory(lastTextureColorState, sizeof(lastTextureColorState));
430N/A
430N/A opState = STATE_CHANGE;
430N/A
430N/A if (pResourceMgr == NULL) {
430N/A res = D3DResourceManager::CreateInstance(this, &pResourceMgr);
430N/A } else {
430N/A res = pResourceMgr->Init(this);
430N/A }
430N/A RETURN_STATUS_IF_FAILED(res);
430N/A
430N/A if (pVCacher == NULL) {
430N/A res = D3DVertexCacher::CreateInstance(this, &pVCacher);
430N/A } else {
430N/A res = pVCacher->Init(this);
430N/A }
430N/A RETURN_STATUS_IF_FAILED(res);
430N/A
430N/A if (pMaskCache == NULL) {
430N/A res = D3DMaskCache::CreateInstance(this, &pMaskCache);
430N/A } else{
430N/A res = pMaskCache->Init(this);
430N/A }
430N/A RETURN_STATUS_IF_FAILED(res);
430N/A
430N/A if (pLCDGlyphCache != NULL) {
430N/A if (FAILED(res = pLCDGlyphCache->Init(this))) {
430N/A // we can live without the cache
430N/A SAFE_DELETE(pLCDGlyphCache);
430N/A res = S_OK;
430N/A }
430N/A }
430N/A
430N/A if (pGrayscaleGlyphCache != NULL) {
430N/A if (FAILED(res = pGrayscaleGlyphCache->Init(this))) {
430N/A // we can live without the cache
430N/A SAFE_DELETE(pGrayscaleGlyphCache);
430N/A res = S_OK;
430N/A }
430N/A }
0N/A
0N/A D3DMATRIX tx;
0N/A D3DUtils_SetIdentityMatrix(&tx);
430N/A pd3dDevice->SetTransform(D3DTS_WORLD, &tx);
430N/A bIsIdentityTx = TRUE;
430N/A
430N/A if (pSyncQuery == NULL) {
430N/A // this is allowed to fail, do not propagate the error
430N/A if (FAILED(pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pSyncQuery))) {
430N/A J2dRlsTraceLn(J2D_TRACE_WARNING,
430N/A "D3DContext::InitDevice: sync query not available");
430N/A pSyncQuery = NULL;
430N/A }
430N/A }
430N/A if (pSyncRTRes == NULL) {
430N/A D3DFORMAT format;
430N/A if (FAILED(GetResourceManager()->
430N/A CreateRTSurface(32, 32, TRUE, TRUE, &format, &pSyncRTRes))) {
430N/A J2dRlsTraceLn(J2D_TRACE_WARNING,
430N/A "D3DContext::InitDevice: "
430N/A "error creating sync surface");
430N/A }
430N/A }
0N/A
0N/A bBeginScenePending = FALSE;
0N/A
430N/A J2dRlsTraceLn1(J2D_TRACE_INFO,
430N/A "D3DContext::InitDefice: successfully initialized device %d",
430N/A adapterOrdinal);
430N/A
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::CheckAndResetDevice()
430N/A{
430N/A HRESULT res = E_FAIL;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::CheckAndResetDevice");
0N/A
430N/A if (pd3dDevice != NULL) {
430N/A if (FAILED(res = pd3dDevice->TestCooperativeLevel())) {
430N/A if (res == D3DERR_DEVICELOST) {
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d is still lost",
430N/A adapterOrdinal);
430N/A // nothing to be done here, wait for D3DERR_DEVICENOTRESET
430N/A return res;
430N/A } else if (res == D3DERR_DEVICENOTRESET) {
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d needs to be reset",
430N/A adapterOrdinal);
430N/A res = ResetContext();
430N/A } else {
430N/A // some unexpected error
430N/A DebugPrintD3DError(res, "D3DContext::CheckAndResetDevice: "\
430N/A "unknown error %x from TestCooperativeLevel");
430N/A }
430N/A } else {
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d is not lost",
430N/A adapterOrdinal);
0N/A }
0N/A } else {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE, " null device");
430N/A }
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::ResetContext()
430N/A{
430N/A HRESULT res = E_FAIL;
430N/A
430N/A J2dRlsTraceLn(J2D_TRACE_INFO, "D3DContext::ResetContext");
430N/A if (pd3dDevice != NULL) {
430N/A D3DPRESENT_PARAMETERS newParams;
430N/A
430N/A newParams = curParams;
430N/A
430N/A if (newParams.Windowed) {
430N/A // reset to the current display mode if we're windowed,
430N/A // otherwise to the display mode we were in when the device
430N/A // was lost
430N/A newParams.BackBufferFormat = D3DFMT_UNKNOWN;
430N/A newParams.FullScreen_RefreshRateInHz = 0;
430N/A newParams.BackBufferWidth = 0;
430N/A newParams.BackBufferHeight = 0;
430N/A }
430N/A res = ConfigureContext(&newParams);
0N/A }
0N/A return res;
0N/A}
0N/A
0N/AHRESULT
430N/AD3DContext::ConfigureContext(D3DPRESENT_PARAMETERS *pNewParams)
0N/A{
430N/A J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DContext::ConfigureContext device %d",
430N/A adapterOrdinal);
430N/A HRESULT res = S_OK;
430N/A D3DFORMAT stencilFormat;
430N/A HWND focusHWND = D3DPipelineManager::GetInstance()->GetCurrentFocusWindow();
430N/A D3DDEVTYPE devType = D3DPipelineManager::GetInstance()->GetDeviceType();
430N/A // this is needed so that we can find the stencil buffer format
430N/A if (pNewParams->BackBufferFormat == D3DFMT_UNKNOWN) {
430N/A D3DDISPLAYMODE dm;
430N/A
430N/A pd3dObject->GetAdapterDisplayMode(adapterOrdinal, &dm);
430N/A pNewParams->BackBufferFormat = dm.Format;
430N/A }
430N/A
430N/A stencilFormat =
430N/A D3DPipelineManager::GetInstance()->GetMatchingDepthStencilFormat(
430N/A adapterOrdinal,
430N/A pNewParams->BackBufferFormat, pNewParams->BackBufferFormat);
430N/A
430N/A pNewParams->EnableAutoDepthStencil = TRUE;
430N/A pNewParams->AutoDepthStencilFormat = stencilFormat;
430N/A
430N/A // do not set device window in the windowed mode, we use additional
430N/A // swap chains for rendering, the default chain is not used. otherwise
430N/A // our scratch focus window will be made visible
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE, " windowed=%d",pNewParams->Windowed);
430N/A if (pNewParams->Windowed) {
430N/A pNewParams->hDeviceWindow = (HWND)0;
430N/A }
430N/A
430N/A // The focus window may change when we're entering/exiting the full-screen
430N/A // mode. It may either be set to the default focus window (when there are
430N/A // no more devices in fs mode), or to fs window for another device
430N/A // in fs mode. See D3DPipelineManager::GetCurrentFocusWindow.
430N/A if (pd3dDevice != NULL) {
430N/A D3DDEVICE_CREATION_PARAMETERS cParams;
430N/A pd3dDevice->GetCreationParameters(&cParams);
430N/A if (cParams.hFocusWindow != focusHWND) {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE,
430N/A " focus window changed, need to recreate the device");
430N/A
430N/A // if fs -> windowed, first exit fs, then recreate, otherwise
430N/A // the screen might be left in a different display mode
430N/A if (pNewParams->Windowed && !curParams.Windowed) {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE,
430N/A " exiting full-screen mode, reset the device");
430N/A curParams.Windowed = FALSE;
430N/A ReleaseDefPoolResources();
430N/A res = pd3dDevice->Reset(&curParams);
430N/A
430N/A if (FAILED(res)) {
430N/A DebugPrintD3DError(res, "D3DContext::ConfigureContext: "\
430N/A "cound not reset the device");
430N/A }
430N/A }
430N/A
430N/A // note that here we should release all device resources, not only
430N/A // thos in the default pool since the device is released
430N/A ReleaseContextResources();
430N/A SAFE_RELEASE(pd3dDevice);
430N/A }
0N/A }
0N/A
430N/A if (pd3dDevice != NULL) {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE, " resetting the device");
430N/A
430N/A ReleaseDefPoolResources();
430N/A
430N/A if (pNewParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE &&
430N/A !IsImmediateIntervalSupported())
430N/A {
430N/A pNewParams->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
430N/A }
430N/A
430N/A res = pd3dDevice->Reset(pNewParams);
430N/A if (FAILED(res)) {
430N/A DebugPrintD3DError(res,
430N/A "D3DContext::ConfigureContext: cound not reset the device");
430N/A return res;
430N/A }
430N/A J2dRlsTraceLn1(J2D_TRACE_INFO,
430N/A "D3DContext::ConfigureContext: successfully reset device: %d",
430N/A adapterOrdinal);
430N/A } else {
430N/A D3DCAPS9 d3dCaps;
430N/A DWORD dwBehaviorFlags;
430N/A
430N/A J2dTraceLn(J2D_TRACE_VERBOSE, " creating a new device");
430N/A
430N/A if (FAILED(res = pd3dObject->GetDeviceCaps(adapterOrdinal,
430N/A devType, &d3dCaps)))
430N/A {
430N/A DebugPrintD3DError(res,
430N/A "D3DContext::ConfigureContext: failed to get caps");
430N/A return res;
430N/A }
430N/A
430N/A if (pNewParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE &&
430N/A !(d3dCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE))
430N/A {
430N/A pNewParams->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
430N/A }
0N/A
430N/A // not preserving fpu control word could cause issues (4860749)
430N/A dwBehaviorFlags = D3DCREATE_FPU_PRESERVE;
430N/A
430N/A J2dRlsTrace(J2D_TRACE_VERBOSE,
430N/A "[V] dwBehaviorFlags=D3DCREATE_FPU_PRESERVE|");
430N/A if (d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
430N/A J2dRlsTrace(J2D_TRACE_VERBOSE,
430N/A "D3DCREATE_HARDWARE_VERTEXPROCESSING");
430N/A dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
430N/A } else {
430N/A J2dRlsTrace(J2D_TRACE_VERBOSE,
430N/A "D3DCREATE_SOFTWARE_VERTEXPROCESSING");
430N/A dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
430N/A }
430N/A // Handling focus changes by ourselves proved to be problematic,
430N/A // so we're reverting back to D3D handling
430N/A // dwBehaviorFlags |= D3DCREATE_NOWINDOWCHANGES;
430N/A J2dRlsTrace(J2D_TRACE_VERBOSE,"\n");
430N/A
430N/A if (FAILED(res = pd3dObject->CreateDevice(adapterOrdinal, devType,
430N/A focusHWND,
430N/A dwBehaviorFlags,
430N/A pNewParams, &pd3dDevice)))
430N/A {
430N/A DebugPrintD3DError(res,
430N/A "D3DContext::ConfigureContext: error creating d3d device");
430N/A return res;
430N/A }
430N/A J2dRlsTraceLn1(J2D_TRACE_INFO,
430N/A "D3DContext::ConfigureContext: successfully created device: %d",
430N/A adapterOrdinal);
430N/A bIsHWRasterizer = (devType == D3DDEVTYPE_HAL);
430N/A }
430N/A
430N/A curParams = *pNewParams;
430N/A // during the creation of the device d3d modifies this field, we reset
430N/A // it back to 0
430N/A curParams.Flags = 0;
430N/A
430N/A if (FAILED(res = InitDevice(pd3dDevice))) {
430N/A ReleaseContextResources();
0N/A return res;
0N/A }
0N/A
430N/A res = InitContextCaps();
430N/A
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::InitContext()
430N/A{
430N/A J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DContext::InitContext device %d",
430N/A adapterOrdinal);
430N/A
430N/A D3DPRESENT_PARAMETERS params;
430N/A ZeroMemory(&params, sizeof(D3DPRESENT_PARAMETERS));
430N/A
430N/A params.hDeviceWindow = 0;
430N/A params.Windowed = TRUE;
430N/A params.BackBufferCount = 1;
430N/A params.BackBufferFormat = D3DFMT_UNKNOWN;
430N/A params.SwapEffect = D3DSWAPEFFECT_DISCARD;
430N/A params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
430N/A
430N/A return ConfigureContext(&params);
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::Sync()
430N/A{
430N/A HRESULT res = S_OK;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::Sync");
430N/A
430N/A if (pSyncQuery != NULL) {
430N/A J2dTrace(J2D_TRACE_VERBOSE, " flushing the device queue..");
430N/A while (S_FALSE ==
430N/A (res = pSyncQuery->GetData(NULL, 0, D3DGETDATA_FLUSH))) ;
430N/A J2dTrace(J2D_TRACE_VERBOSE, ".. done\n");
430N/A }
430N/A if (pSyncRTRes != NULL) {
430N/A D3DLOCKED_RECT lr;
430N/A IDirect3DSurface9 *pSurface = pSyncRTRes->GetSurface();
430N/A if (SUCCEEDED(pSurface->LockRect(&lr, NULL, D3DLOCK_NOSYSLOCK))) {
430N/A pSurface->UnlockRect();
430N/A }
430N/A }
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::SaveState()
430N/A{
430N/A HRESULT res;
430N/A
430N/A RETURN_STATUS_IF_NULL(pd3dDevice, S_OK);
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SaveState");
430N/A
430N/A FlushVertexQueue();
430N/A UpdateState(STATE_CHANGE);
430N/A
430N/A if (pStateBlock != NULL) {
430N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "D3DContext::SaveState: existing state block!");
430N/A SAFE_RELEASE(pStateBlock);
0N/A }
0N/A
430N/A if (SUCCEEDED(res =
430N/A pd3dDevice->CreateStateBlock(D3DSBT_ALL, &pStateBlock)))
430N/A {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE, " created state block");
430N/A } else {
430N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "D3DContext::SaveState: failed to create state block");
430N/A }
430N/A ZeroMemory(lastTexture, sizeof(lastTexture));
430N/A
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::RestoreState()
430N/A{
430N/A HRESULT res = S_OK;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::RestoreState");
430N/A
430N/A FlushVertexQueue();
430N/A UpdateState(STATE_CHANGE);
430N/A
430N/A if (pStateBlock != NULL) {
430N/A if (SUCCEEDED(res = pStateBlock->Apply())) {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE, " restored device state");
430N/A } else {
430N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "D3DContext::RestoreState: failed to restore state");
430N/A }
430N/A SAFE_RELEASE(pStateBlock);
430N/A } else {
430N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "D3DContext::RestoreState: empty state block!");
430N/A }
430N/A ZeroMemory(lastTexture, sizeof(lastTexture));
430N/A
430N/A return res;
430N/A}
430N/A
430N/A#define POINT_FILTER_CAP (D3DPTFILTERCAPS_MAGFPOINT|D3DPTFILTERCAPS_MINFPOINT)
430N/A#define LINEAR_FILTER_CAP (D3DPTFILTERCAPS_MAGFLINEAR|D3DPTFILTERCAPS_MINFLINEAR)
430N/A
430N/ABOOL
430N/AD3DContext::IsStretchRectFilteringSupported(D3DTEXTUREFILTERTYPE fType)
430N/A{
430N/A if (fType == D3DTEXF_POINT) {
430N/A return ((devCaps.StretchRectFilterCaps & POINT_FILTER_CAP) != 0);
430N/A }
430N/A if (fType == D3DTEXF_LINEAR) {
430N/A return ((devCaps.StretchRectFilterCaps & LINEAR_FILTER_CAP) != 0);
430N/A }
430N/A return FALSE;
430N/A}
430N/A
430N/ABOOL
430N/AD3DContext::IsTextureFilteringSupported(D3DTEXTUREFILTERTYPE fType)
430N/A{
430N/A if (fType == D3DTEXF_POINT) {
430N/A return ((devCaps.TextureFilterCaps & POINT_FILTER_CAP) != 0);
430N/A }
430N/A if (fType == D3DTEXF_LINEAR) {
430N/A return ((devCaps.TextureFilterCaps & LINEAR_FILTER_CAP) != 0);
430N/A }
430N/A return FALSE;
430N/A}
430N/A
430N/ABOOL
430N/AD3DContext::IsTextureFormatSupported(D3DFORMAT format, DWORD usage)
430N/A{
430N/A HRESULT hr = pd3dObject->CheckDeviceFormat(adapterOrdinal,
430N/A devCaps.DeviceType,
430N/A curParams.BackBufferFormat,
430N/A usage,
430N/A D3DRTYPE_TEXTURE,
430N/A format);
430N/A return SUCCEEDED( hr );
430N/A}
430N/A
430N/ABOOL
430N/AD3DContext::IsDepthStencilBufferOk(D3DSURFACE_DESC *pTargetDesc)
430N/A{
430N/A IDirect3DSurface9 *pStencil;
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::IsDepthStencilBufferOk");
430N/A
430N/A if (SUCCEEDED(pd3dDevice->GetDepthStencilSurface(&pStencil))) {
430N/A D3DSURFACE_DESC descStencil;
430N/A pStencil->GetDesc(&descStencil);
430N/A pStencil->Release();
430N/A
430N/A D3DDISPLAYMODE dm;
430N/A return
430N/A (SUCCEEDED(pd3dDevice->GetDisplayMode(0, &dm)) &&
430N/A pTargetDesc->Width <= descStencil.Width &&
430N/A pTargetDesc->Height <= descStencil.Height &&
430N/A SUCCEEDED(pd3dObject->CheckDepthStencilMatch(
430N/A adapterOrdinal,
430N/A devCaps.DeviceType,
430N/A dm.Format, pTargetDesc->Format,
430N/A descStencil.Format)));
430N/A }
430N/A J2dTraceLn(J2D_TRACE_VERBOSE,
430N/A " current stencil buffer is not compatible with new Render Target");
430N/A
430N/A return false;
430N/A}
430N/A
430N/A
430N/A
430N/AHRESULT
430N/AD3DContext::InitDepthStencilBuffer(D3DSURFACE_DESC *pTargetDesc)
430N/A{
430N/A HRESULT res;
430N/A IDirect3DSurface9 *pBB;
430N/A D3DDISPLAYMODE dm;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::InitDepthStencilBuffer");
430N/A
430N/A if (FAILED(res = pd3dDevice->GetDisplayMode(0, &dm))) {
430N/A return res;
430N/A }
430N/A
430N/A D3DFORMAT newFormat =
430N/A D3DPipelineManager::GetInstance()->GetMatchingDepthStencilFormat(
430N/A adapterOrdinal, dm.Format, pTargetDesc->Format);
430N/A
430N/A res = pd3dDevice->CreateDepthStencilSurface(
430N/A pTargetDesc->Width, pTargetDesc->Height,
430N/A newFormat, D3DMULTISAMPLE_NONE, 0, false, &pBB, 0);
430N/A if (SUCCEEDED(res)) {
430N/A res = pd3dDevice->SetDepthStencilSurface(pBB);
430N/A pBB->Release();
0N/A }
0N/A
0N/A return res;
0N/A}
0N/A
0N/A
0N/AHRESULT
430N/AD3DContext::SetRenderTarget(IDirect3DSurface9 *pSurface)
0N/A{
0N/A static D3DMATRIX tx;
430N/A HRESULT res;
430N/A D3DSURFACE_DESC descNew;
430N/A IDirect3DSurface9 *pCurrentTarget;
0N/A
430N/A J2dTraceLn1(J2D_TRACE_INFO,
430N/A "D3DContext::SetRenderTarget: pSurface=0x%x",
430N/A pSurface);
0N/A
430N/A RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
430N/A RETURN_STATUS_IF_NULL(pSurface, E_FAIL);
0N/A
430N/A pSurface->GetDesc(&descNew);
0N/A
430N/A if (SUCCEEDED(res = pd3dDevice->GetRenderTarget(0, &pCurrentTarget))) {
430N/A if (pCurrentTarget != pSurface) {
430N/A FlushVertexQueue();
430N/A if (FAILED(res = pd3dDevice->SetRenderTarget(0, pSurface))) {
430N/A DebugPrintD3DError(res, "D3DContext::SetRenderTarget: "\
430N/A "error setting render target");
430N/A SAFE_RELEASE(pCurrentTarget);
430N/A return res;
430N/A }
0N/A
430N/A if (!IsDepthStencilBufferOk(&descNew)) {
430N/A if (FAILED(res = InitDepthStencilBuffer(&descNew))) {
430N/A SAFE_RELEASE(pCurrentTarget);
430N/A return res;
430N/A }
430N/A }
430N/A }
430N/A SAFE_RELEASE(pCurrentTarget);
0N/A }
430N/A // we set the transform even if the render target didn't change;
430N/A // this is because in some cases (fs mode) we use the default SwapChain of
430N/A // the device, and its render target will be the same as the device's, and
430N/A // we have to set the matrix correctly. This shouldn't be a performance
430N/A // issue as render target changes are relatively rare
430N/A D3DUtils_SetOrthoMatrixOffCenterLH(&tx,
430N/A (float)descNew.Width,
430N/A (float)descNew.Height);
430N/A pd3dDevice->SetTransform(D3DTS_PROJECTION, &tx);
0N/A
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE, " current render target=0x%x", pSurface);
0N/A return res;
0N/A}
0N/A
0N/AHRESULT
430N/AD3DContext::ResetTransform()
430N/A{
430N/A HRESULT res = S_OK;
430N/A D3DMATRIX tx;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ResetTransform");
430N/A if (pd3dDevice == NULL) {
430N/A return E_FAIL;
430N/A }
430N/A
430N/A // no need for state change, just flush the queue
430N/A FlushVertexQueue();
430N/A
430N/A D3DUtils_SetIdentityMatrix(&tx);
430N/A if (FAILED(res = pd3dDevice->SetTransform(D3DTS_WORLD, &tx))) {
430N/A DebugPrintD3DError(res, "D3DContext::SetTransform failed");
430N/A }
430N/A bIsIdentityTx = TRUE;
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::SetTransform(jdouble m00, jdouble m10,
0N/A jdouble m01, jdouble m11,
0N/A jdouble m02, jdouble m12)
0N/A{
430N/A HRESULT res = S_OK;
430N/A D3DMATRIX tx, tx1;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetTransform");
430N/A if (pd3dDevice == NULL) {
430N/A return E_FAIL;
0N/A }
0N/A
430N/A // no need for state change, just flush the queue
430N/A FlushVertexQueue();
430N/A
430N/A // In order to correctly map texels to pixels we need to
430N/A // adjust geometry by -0.5f in the transformed space.
430N/A // In order to do that we first create a translated matrix
430N/A // and then concatenate it with the world transform.
430N/A //
430N/A // Note that we only use non-id transform with DrawTexture,
430N/A // the rest is rendered pre-transformed.
430N/A //
430N/A // The identity transform for textures is handled in
430N/A // D3DVertexCacher::DrawTexture() because shifting by -0.5 for id
430N/A // transform breaks lines rendering.
430N/A
430N/A ZeroMemory(&tx1, sizeof(D3DMATRIX));
430N/A
430N/A tx1._11 = (float)m00;
430N/A tx1._12 = (float)m10;
430N/A tx1._21 = (float)m01;
430N/A tx1._22 = (float)m11;
430N/A tx1._41 = (float)m02;
430N/A tx1._42 = (float)m12;
430N/A
430N/A tx1._33 = 1.0f;
430N/A tx1._44 = 1.0f;
430N/A
430N/A D3DUtils_SetIdentityMatrix(&tx);
430N/A tx._41 = -0.5f;
430N/A tx._42 = -0.5f;
430N/A D3DUtils_2DConcatenateM(&tx, &tx1);
430N/A
0N/A J2dTraceLn4(J2D_TRACE_VERBOSE,
0N/A " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14);
0N/A J2dTraceLn4(J2D_TRACE_VERBOSE,
0N/A " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24);
0N/A J2dTraceLn4(J2D_TRACE_VERBOSE,
0N/A " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34);
0N/A J2dTraceLn4(J2D_TRACE_VERBOSE,
0N/A " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44);
430N/A if (FAILED(res = pd3dDevice->SetTransform(D3DTS_WORLD, &tx))) {
430N/A DebugPrintD3DError(res, "D3DContext::SetTransform failed");
430N/A }
430N/A bIsIdentityTx = FALSE;
430N/A
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::SetRectClip(int x1, int y1, int x2, int y2)
430N/A{
430N/A HRESULT res = S_OK;
430N/A D3DSURFACE_DESC desc;
430N/A IDirect3DSurface9 *pCurrentTarget;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetRectClip");
430N/A J2dTraceLn4(J2D_TRACE_VERBOSE,
430N/A " x1=%-4d y1=%-4d x2=%-4d y2=%-4d",
430N/A x1, y1, x2, y2);
430N/A
430N/A RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
430N/A
430N/A // no need for state change, just flush the queue
430N/A FlushVertexQueue();
430N/A
430N/A pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
430N/A
430N/A res = pd3dDevice->GetRenderTarget(0, &pCurrentTarget);
430N/A RETURN_STATUS_IF_FAILED(res);
430N/A
430N/A pCurrentTarget->GetDesc(&desc);
430N/A SAFE_RELEASE(pCurrentTarget);
430N/A
430N/A if (x1 <= 0 && y1 <= 0 &&
430N/A (UINT)x2 >= desc.Width && (UINT)y2 >= desc.Height)
430N/A {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE,
430N/A " disabling clip (== render target dimensions)");
430N/A return pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
0N/A }
0N/A
430N/A // clip to the dimensions of the target surface, otherwise
430N/A // SetScissorRect will fail
430N/A if (x1 < 0) x1 = 0;
430N/A if (y1 < 0) y1 = 0;
430N/A if ((UINT)x2 > desc.Width) x2 = desc.Width;
430N/A if ((UINT)y2 > desc.Height) y2 = desc.Height;
430N/A if (x1 > x2) x2 = x1 = 0;
430N/A if (y1 > y2) y2 = y1 = 0;
430N/A RECT newRect = { x1, y1, x2, y2 };
430N/A if (SUCCEEDED(res = pd3dDevice->SetScissorRect(&newRect))) {
430N/A res = pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
430N/A } else {
430N/A DebugPrintD3DError(res, "Error setting scissor rect");
430N/A J2dRlsTraceLn4(J2D_TRACE_ERROR,
430N/A " x1=%-4d y1=%-4d x2=%-4d y2=%-4d",
430N/A x1, y1, x2, y2);
430N/A }
430N/A
0N/A return res;
0N/A}
0N/A
430N/AHRESULT
430N/AD3DContext::ResetClip()
430N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ResetClip");
430N/A // no need for state change, just flush the queue
430N/A FlushVertexQueue();
430N/A pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
430N/A return pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
430N/A}
430N/A
430N/AClipType
430N/AD3DContext::GetClipType()
430N/A{
430N/A // REMIND: this method could be optimized: we could keep the
430N/A // clip state around when re/setting the clip instead of asking
430N/A // every time.
430N/A DWORD zEnabled = 0;
430N/A DWORD stEnabled = 0;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::GetClipType");
430N/A pd3dDevice->GetRenderState(D3DRS_SCISSORTESTENABLE, &stEnabled);
430N/A if (stEnabled) {
430N/A return CLIP_RECT;
430N/A }
430N/A pd3dDevice->GetRenderState(D3DRS_ZENABLE, &zEnabled);
430N/A if (zEnabled) {
430N/A return CLIP_SHAPE;
430N/A }
430N/A return CLIP_NONE;
430N/A}
430N/A
430N/A
0N/A/**
0N/A * This method assumes that ::SetRenderTarget has already
0N/A * been called. SetRenderTarget creates and attaches a
0N/A * depth buffer to the target surface prior to setting it
0N/A * as target surface to the device.
0N/A */
430N/ADWORD dwAlphaSt, dwSrcBlendSt, dwDestBlendSt;
430N/AD3DMATRIX tx, idTx;
430N/A
0N/AHRESULT
430N/AD3DContext::BeginShapeClip()
0N/A{
430N/A HRESULT res = S_OK;
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::BeginShapeClip");
0N/A
430N/A UpdateState(STATE_CHANGE);
0N/A
430N/A pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
0N/A
430N/A // save alpha blending state
430N/A pd3dDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &dwAlphaSt);
430N/A pd3dDevice->GetRenderState(D3DRS_SRCBLEND, &dwSrcBlendSt);
430N/A pd3dDevice->GetRenderState(D3DRS_DESTBLEND, &dwDestBlendSt);
0N/A
430N/A pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
430N/A pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
430N/A pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
0N/A
430N/A pd3dDevice->GetTransform(D3DTS_WORLD, &tx);
0N/A D3DUtils_SetIdentityMatrix(&idTx);
430N/A // translate the clip spans by 1.0f in z direction so that the
430N/A // clip spans are rendered to the z buffer
430N/A idTx._43 = 1.0f;
430N/A pd3dDevice->SetTransform(D3DTS_WORLD, &idTx);
0N/A
0N/A // The depth buffer is first cleared with zeroes, which is the farthest
0N/A // plane from the viewer (our projection matrix is an inversed orthogonal
0N/A // transform).
0N/A // To set the clip we'll render the clip spans with Z coordinates of 1.0f
0N/A // (the closest to the viewer). Since all rendering primitives
0N/A // have their vertices' Z coordinate set to 0.0, they will effectively be
0N/A // clipped because the Z depth test for them will fail (vertex with 1.0
0N/A // depth is closer than the one with 0.0f)
430N/A pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
430N/A pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
430N/A pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
430N/A pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0L, 0.0f, 0x0L);
0N/A
430N/A //res = BeginScene(STATE_SHAPE_CLIPOP);
0N/A
0N/A return res;
0N/A}
0N/A
0N/AHRESULT
430N/AD3DContext::EndShapeClip()
0N/A{
430N/A HRESULT res;
0N/A
430N/A // no need for state change, just flush the queue
430N/A res = FlushVertexQueue();
0N/A
430N/A // restore alpha blending state
430N/A pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, dwAlphaSt);
430N/A pd3dDevice->SetRenderState(D3DRS_SRCBLEND, dwSrcBlendSt);
430N/A pd3dDevice->SetRenderState(D3DRS_DESTBLEND, dwDestBlendSt);
0N/A
430N/A // resore the transform
430N/A pd3dDevice->SetTransform(D3DTS_WORLD, &tx);
0N/A
430N/A // Enable the depth buffer.
430N/A // We disable further updates to the depth buffer: it should only
430N/A // be updated in SetClip method.
430N/A pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
430N/A pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);
0N/A
0N/A return res;
0N/A}
0N/A
430N/AHRESULT
430N/AD3DContext::UploadTileToTexture(D3DResource *pTextureRes, void *pixels,
430N/A jint dstx, jint dsty,
430N/A jint srcx, jint srcy,
430N/A jint srcWidth, jint srcHeight,
430N/A jint srcStride,
430N/A TileFormat srcFormat,
430N/A jint *pPixelsTouchedL,
430N/A jint* pPixelsTouchedR)
0N/A{
430N/A#ifndef PtrAddBytes
430N/A#define PtrAddBytes(p, b) ((void *) (((intptr_t) (p)) + (b)))
430N/A#define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, (y)*(yinc) + (x)*(xinc))
430N/A#endif // PtrAddBytes
430N/A
430N/A HRESULT res = S_OK;
430N/A IDirect3DTexture9 *pTexture = pTextureRes->GetTexture();
430N/A D3DSURFACE_DESC *pDesc = pTextureRes->GetDesc();
430N/A RECT r = { dstx, dsty, dstx+srcWidth, dsty+srcHeight };
430N/A RECT *pR = &r;
430N/A D3DLOCKED_RECT lockedRect;
430N/A DWORD dwLockFlags = D3DLOCK_NOSYSLOCK;
430N/A // these are only counted for LCD glyph uploads
430N/A jint pixelsTouchedL = 0, pixelsTouchedR = 0;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::UploadTileToTexture");
430N/A J2dTraceLn4(J2D_TRACE_VERBOSE,
430N/A " rect={%-4d, %-4d, %-4d, %-4d}",
430N/A r.left, r.top, r.right, r.bottom);
430N/A
772N/A if (pDesc->Usage == D3DUSAGE_DYNAMIC) {
772N/A // it is safe to lock with discard because we don't care about the
772N/A // contents of dynamic textures and dstx,dsty for this case is
772N/A // always 0,0 because we are uploading into a tile texture
430N/A dwLockFlags |= D3DLOCK_DISCARD;
430N/A pR = NULL;
430N/A }
430N/A
430N/A if (FAILED(res = pTexture->LockRect(0, &lockedRect, pR, dwLockFlags))) {
430N/A DebugPrintD3DError(res,
430N/A "D3DContext::UploadImageToTexture: could "\
430N/A "not lock texture");
430N/A return res;
430N/A }
0N/A
430N/A if (srcFormat == TILEFMT_1BYTE_ALPHA) {
430N/A // either a MaskFill tile, or a grayscale glyph
430N/A if (pDesc->Format == D3DFMT_A8) {
430N/A void *pSrcPixels = PtrCoord(pixels, srcx, 1, srcy, srcStride);
430N/A void *pDstPixels = lockedRect.pBits;
430N/A do {
430N/A memcpy(pDstPixels, pSrcPixels, srcWidth);
430N/A pSrcPixels = PtrAddBytes(pSrcPixels, srcStride);
430N/A pDstPixels = PtrAddBytes(pDstPixels, lockedRect.Pitch);
430N/A } while (--srcHeight > 0);
430N/A }
430N/A else if (pDesc->Format == D3DFMT_A8R8G8B8) {
430N/A jubyte *pSrcPixels = (jubyte*)
430N/A PtrCoord(pixels, srcx, 1, srcy, srcStride);
430N/A jint *pDstPixels = (jint*)lockedRect.pBits;
430N/A for (int yy = 0; yy < srcHeight; yy++) {
430N/A for (int xx = 0; xx < srcWidth; xx++) {
430N/A // only need to set the alpha channel (the D3D texture
430N/A // state will be setup in this case to replicate the
430N/A // alpha channel as needed)
430N/A pDstPixels[xx] = pSrcPixels[xx] << 24;
430N/A }
430N/A pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride);
430N/A pDstPixels = (jint*)PtrAddBytes(pDstPixels, lockedRect.Pitch);
430N/A }
430N/A }
430N/A } else if (srcFormat == TILEFMT_3BYTE_RGB) {
430N/A // LCD glyph with RGB order
430N/A if (pDesc->Format == D3DFMT_R8G8B8) {
430N/A jubyte *pSrcPixels = (jubyte*)
430N/A PtrCoord(pixels, srcx, 3, srcy, srcStride);
430N/A jubyte *pDstPixels = (jubyte*)lockedRect.pBits;
430N/A for (int yy = 0; yy < srcHeight; yy++) {
430N/A for (int xx = 0; xx < srcWidth*3; xx+=3) {
430N/A // alpha channel is ignored in this case
430N/A // (note that this is backwards from what one might
430N/A // expect; it appears that D3DFMT_R8G8B8 is actually
430N/A // laid out in BGR order in memory)
430N/A pDstPixels[xx+0] = pSrcPixels[xx+2];
430N/A pDstPixels[xx+1] = pSrcPixels[xx+1];
430N/A pDstPixels[xx+2] = pSrcPixels[xx+0];
430N/A }
430N/A pixelsTouchedL +=
430N/A (pDstPixels[0+0]|pDstPixels[0+1]|pDstPixels[0+2]) ? 1 : 0;
430N/A jint i = 3*(srcWidth-1);
430N/A pixelsTouchedR +=
430N/A (pDstPixels[i+0]|pDstPixels[i+1]|pDstPixels[i+2]) ? 1 : 0;
430N/A
430N/A pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride);
430N/A pDstPixels = (jubyte*)PtrAddBytes(pDstPixels, lockedRect.Pitch);
430N/A }
430N/A }
430N/A else if (pDesc->Format == D3DFMT_A8R8G8B8) {
430N/A jubyte *pSrcPixels = (jubyte*)
430N/A PtrCoord(pixels, srcx, 3, srcy, srcStride);
430N/A jint *pDstPixels = (jint*)lockedRect.pBits;
430N/A for (int yy = 0; yy < srcHeight; yy++) {
430N/A for (int dx = 0, sx = 0; dx < srcWidth; dx++, sx+=3) {
430N/A // alpha channel is ignored in this case
430N/A jubyte r = pSrcPixels[sx+0];
430N/A jubyte g = pSrcPixels[sx+1];
430N/A jubyte b = pSrcPixels[sx+2];
430N/A pDstPixels[dx] = (r << 16) | (g << 8) | (b);
430N/A }
430N/A pixelsTouchedL += (pDstPixels[0] ? 1 : 0);
430N/A pixelsTouchedR += (pDstPixels[srcWidth-1] ? 1 : 0);
0N/A
430N/A pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride);
430N/A pDstPixels = (jint*)PtrAddBytes(pDstPixels, lockedRect.Pitch);
430N/A }
430N/A }
430N/A } else if (srcFormat == TILEFMT_3BYTE_BGR) {
430N/A // LCD glyph with BGR order
430N/A if (pDesc->Format == D3DFMT_R8G8B8) {
430N/A void *pSrcPixels = PtrCoord(pixels, srcx, 3, srcy, srcStride);
430N/A void *pDstPixels = lockedRect.pBits;
430N/A jubyte *pbDst;
430N/A do {
430N/A // alpha channel is ignored in this case
430N/A // (note that this is backwards from what one might
430N/A // expect; it appears that D3DFMT_R8G8B8 is actually
430N/A // laid out in BGR order in memory)
430N/A memcpy(pDstPixels, pSrcPixels, srcWidth * 3);
430N/A
430N/A pbDst = (jubyte*)pDstPixels;
430N/A pixelsTouchedL +=(pbDst[0+0]|pbDst[0+1]|pbDst[0+2]) ? 1 : 0;
430N/A jint i = 3*(srcWidth-1);
430N/A pixelsTouchedR +=(pbDst[i+0]|pbDst[i+1]|pbDst[i+2]) ? 1 : 0;
430N/A
430N/A pSrcPixels = PtrAddBytes(pSrcPixels, srcStride);
430N/A pDstPixels = PtrAddBytes(pDstPixels, lockedRect.Pitch);
430N/A } while (--srcHeight > 0);
430N/A }
430N/A else if (pDesc->Format == D3DFMT_A8R8G8B8) {
430N/A jubyte *pSrcPixels = (jubyte*)
430N/A PtrCoord(pixels, srcx, 3, srcy, srcStride);
430N/A jint *pDstPixels = (jint*)lockedRect.pBits;
430N/A for (int yy = 0; yy < srcHeight; yy++) {
430N/A for (int dx = 0, sx = 0; dx < srcWidth; dx++, sx+=3) {
430N/A // alpha channel is ignored in this case
430N/A jubyte b = pSrcPixels[sx+0];
430N/A jubyte g = pSrcPixels[sx+1];
430N/A jubyte r = pSrcPixels[sx+2];
430N/A pDstPixels[dx] = (r << 16) | (g << 8) | (b);
430N/A }
430N/A pixelsTouchedL += (pDstPixels[0] ? 1 : 0);
430N/A pixelsTouchedR += (pDstPixels[srcWidth-1] ? 1 : 0);
430N/A
430N/A pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride);
430N/A pDstPixels = (jint*)PtrAddBytes(pDstPixels, lockedRect.Pitch);
430N/A }
430N/A }
430N/A } else if (srcFormat == TILEFMT_4BYTE_ARGB_PRE) {
430N/A // MaskBlit tile
430N/A if (pDesc->Format == D3DFMT_A8R8G8B8) {
430N/A void *pSrcPixels = PtrCoord(pixels, srcx, 4, srcy, srcStride);
430N/A void *pDstPixels = lockedRect.pBits;
430N/A do {
430N/A memcpy(pDstPixels, pSrcPixels, srcWidth * 4);
430N/A pSrcPixels = PtrAddBytes(pSrcPixels, srcStride);
430N/A pDstPixels = PtrAddBytes(pDstPixels, lockedRect.Pitch);
430N/A } while (--srcHeight > 0);
430N/A }
0N/A } else {
430N/A // should not happen, no-op just in case...
430N/A }
430N/A
430N/A if (pPixelsTouchedL) {
430N/A *pPixelsTouchedL = pixelsTouchedL;
0N/A }
430N/A if (pPixelsTouchedR) {
430N/A *pPixelsTouchedR = pixelsTouchedR;
430N/A }
430N/A
430N/A return pTexture->UnlockRect(0);
0N/A}
0N/A
430N/AHRESULT
430N/AD3DContext::InitLCDGlyphCache()
430N/A{
430N/A if (pLCDGlyphCache == NULL) {
430N/A return D3DGlyphCache::CreateInstance(this, CACHE_LCD, &pLCDGlyphCache);
430N/A }
430N/A return S_OK;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DContext::InitGrayscaleGlyphCache()
430N/A{
430N/A if (pGrayscaleGlyphCache == NULL) {
430N/A return D3DGlyphCache::CreateInstance(this, CACHE_GRAY,
430N/A &pGrayscaleGlyphCache);
430N/A }
430N/A return S_OK;
430N/A}
430N/A
430N/AHRESULT
0N/AD3DContext::ResetComposite()
0N/A{
0N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ResetComposite");
430N/A
430N/A RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
430N/A
430N/A HRESULT res = UpdateState(STATE_CHANGE);
430N/A pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
0N/A extraAlpha = 1.0f;
430N/A return res;
0N/A}
0N/A
430N/AHRESULT
0N/AD3DContext::SetAlphaComposite(jint rule, jfloat ea, jint flags)
0N/A{
430N/A HRESULT res;
0N/A J2dTraceLn3(J2D_TRACE_INFO,
0N/A "D3DContext::SetAlphaComposite: rule=%-1d ea=%f flags=%d",
0N/A rule, ea, flags);
0N/A
430N/A RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
430N/A
430N/A res = UpdateState(STATE_CHANGE);
0N/A
0N/A // we can safely disable blending when:
0N/A // - comp is SrcNoEa or SrcOverNoEa, and
0N/A // - the source is opaque
430N/A // (turning off blending can have a large positive impact on performance)
0N/A if ((rule == RULE_Src || rule == RULE_SrcOver) &&
0N/A (ea == 1.0f) &&
0N/A (flags & D3DC_SRC_IS_OPAQUE))
430N/A {
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE,
430N/A " disabling alpha comp rule=%-1d ea=1.0 src=opq)", rule);
430N/A pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
430N/A } else {
0N/A J2dTraceLn2(J2D_TRACE_VERBOSE,
0N/A " enabling alpha comp (rule=%-1d ea=%f)", rule, ea);
430N/A pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
0N/A
430N/A pd3dDevice->SetRenderState(D3DRS_SRCBLEND,
430N/A StdBlendRules[rule].src);
430N/A pd3dDevice->SetRenderState(D3DRS_DESTBLEND,
430N/A StdBlendRules[rule].dst);
0N/A }
0N/A
430N/A extraAlpha = ea;
0N/A return res;
0N/A}
0N/A
430N/A#ifdef UPDATE_TX
0N/A
430N/A// Note: this method of adjusting pixel to texel mapping proved to be
430N/A// difficult to perfect. The current variation works great for id,
430N/A// scale (including all kinds of flips) transforms, but not still not
430N/A// for generic transforms.
430N/A//
430N/A// Since we currently only do DrawTexture with non-id transform we instead
430N/A// adjust the geometry (see D3DVertexCacher::DrawTexture(), SetTransform())
430N/A//
430N/A// In order to enable this code path UpdateTextureTransforms needs to
430N/A// be called in SetTexture(), SetTransform() and ResetTranform().
430N/AHRESULT
430N/AD3DContext::UpdateTextureTransforms(DWORD dwSamplerToUpdate)
430N/A{
430N/A HRESULT res = S_OK;
430N/A DWORD dwSampler, dwMaxSampler;
0N/A
430N/A if (dwSamplerToUpdate == -1) {
430N/A // update all used samplers, dwMaxSampler will be set to max
430N/A dwSampler = 0;
430N/A dwSampler = MAX_USED_TEXTURE_SAMPLER;
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::UpdateTextureTransforms: "\
430N/A "updating all samplers");
430N/A } else {
430N/A // update only given sampler, dwMaxSampler will be set to it as well
430N/A dwSampler = dwSamplerToUpdate;
430N/A dwMaxSampler = dwSamplerToUpdate;
430N/A J2dTraceLn1(J2D_TRACE_INFO, "D3DContext::UpdateTextureTransforms: "\
430N/A "updating sampler %d", dwSampler);
0N/A }
0N/A
430N/A do {
430N/A D3DTRANSFORMSTATETYPE state =
430N/A (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + dwSampler);
430N/A IDirect3DTexture9 *pTexture = lastTexture[dwSampler];
430N/A
430N/A if (pTexture != NULL) {
430N/A D3DMATRIX mt, tx;
430N/A D3DSURFACE_DESC texDesc;
430N/A
430N/A pd3dDevice->GetTransform(D3DTS_WORLD, &tx);
430N/A J2dTraceLn4(10,
430N/A " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14);
430N/A J2dTraceLn4(10,
430N/A " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24);
430N/A J2dTraceLn4(10,
430N/A " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34);
430N/A J2dTraceLn4(10,
430N/A " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44);
0N/A
430N/A // this formula works for scales and flips
430N/A if (tx._11 == 0.0f) {
430N/A tx._11 = tx._12;
430N/A }
430N/A if (tx._22 == 0.0f) {
430N/A tx._22 = tx._21;
430N/A }
430N/A
430N/A pTexture->GetLevelDesc(0, &texDesc);
430N/A
430N/A // shift by .5 texel, but take into account
430N/A // the scale factor of the device transform
430N/A
430N/A // REMIND: this approach is not entirely correct,
430N/A // as it only takes into account the scale of the device
430N/A // transform.
430N/A mt._31 = (1.0f / (2.0f * texDesc.Width * tx._11));
430N/A mt._32 = (1.0f / (2.0f * texDesc.Height * tx._22));
430N/A J2dTraceLn2(J2D_TRACE_VERBOSE, " offsets: tx=%f ty=%f",
430N/A mt._31, mt._32);
430N/A
430N/A pd3dDevice->SetTextureStageState(dwSampler,
430N/A D3DTSS_TEXTURETRANSFORMFLAGS,
430N/A D3DTTFF_COUNT2);
430N/A res = pd3dDevice->SetTransform(state, &mt);
430N/A } else {
430N/A res = pd3dDevice->SetTextureStageState(dwSampler,
430N/A D3DTSS_TEXTURETRANSFORMFLAGS,
430N/A D3DTTFF_DISABLE);
0N/A }
430N/A dwSampler++;
430N/A } while (dwSampler <= dwMaxSampler);
0N/A
0N/A return res;
0N/A}
430N/A#endif // UPDATE_TX
0N/A
0N/A/**
0N/A * We go into the pains of maintaining the list of set textures
0N/A * instead of just calling GetTexture() and comparing the old one
0N/A * with the new one because it's actually noticeably slower to call
0N/A * GetTexture() (note that we'd have to then call Release() on the
0N/A * texture since GetTexture() increases texture's ref. count).
0N/A */
430N/AHRESULT
430N/AD3DContext::SetTexture(IDirect3DTexture9 *pTexture, DWORD dwSampler)
0N/A{
430N/A HRESULT res = S_OK;
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetTexture");
0N/A
430N/A if (dwSampler < 0 || dwSampler > MAX_USED_TEXTURE_SAMPLER) {
0N/A J2dTraceLn1(J2D_TRACE_ERROR,
430N/A "D3DContext::SetTexture: incorrect sampler: %d", dwSampler);
430N/A return E_FAIL;
0N/A }
430N/A if (lastTexture[dwSampler] != pTexture) {
430N/A if (FAILED(res = FlushVertexQueue())) {
430N/A return res;
430N/A }
430N/A J2dTraceLn2(J2D_TRACE_VERBOSE,
430N/A " new texture=0x%x on sampler %d", pTexture, dwSampler);
430N/A res = pd3dDevice->SetTexture(dwSampler, pTexture);
430N/A if (SUCCEEDED(res)) {
430N/A lastTexture[dwSampler] = pTexture;
430N/A // REMIND: see comment at UpdateTextureTransforms
430N/A#ifdef UPDATE_TX
430N/A res = UpdateTextureTransforms(dwSampler);
430N/A#endif
430N/A } else {
430N/A lastTexture[dwSampler] = NULL;
430N/A }
0N/A }
0N/A return res;
0N/A}
0N/A
430N/AHRESULT
430N/AD3DContext::UpdateTextureColorState(DWORD dwState, DWORD dwSampler)
0N/A{
430N/A HRESULT res = S_OK;
0N/A
430N/A if (dwState != lastTextureColorState[dwSampler]) {
430N/A res = pd3dDevice->SetTextureStageState(dwSampler,
430N/A D3DTSS_ALPHAARG1, dwState);
430N/A res = pd3dDevice->SetTextureStageState(dwSampler,
430N/A D3DTSS_COLORARG1, dwState);
430N/A lastTextureColorState[dwSampler] = dwState;
0N/A }
430N/A
430N/A return res;
0N/A}
0N/A
430N/AHRESULT /*NOLOCK*/
0N/AD3DContext::UpdateState(jbyte newState)
0N/A{
430N/A HRESULT res = S_OK;
430N/A
430N/A if (opState == newState) {
430N/A // The op is the same as last time, so we can return immediately.
430N/A return res;
430N/A } else if (opState != STATE_CHANGE) {
430N/A res = FlushVertexQueue();
430N/A }
0N/A
430N/A switch (opState) {
430N/A case STATE_MASKOP:
430N/A pMaskCache->Disable();
430N/A break;
430N/A case STATE_GLYPHOP:
430N/A D3DTR_DisableGlyphVertexCache(this);
430N/A break;
430N/A case STATE_TEXTUREOP:
430N/A // optimization: certain state changes (those marked STATE_CHANGE)
430N/A // are allowed while texturing is enabled.
430N/A // In this case, we can allow previousOp to remain as it is and
430N/A // then return early.
430N/A if (newState == STATE_CHANGE) {
430N/A return res;
430N/A }
430N/A // REMIND: not necessary if we are switching to MASKOP or GLYPHOP
430N/A // (or a complex paint, for that matter), but would that be a
430N/A // worthwhile optimization?
430N/A SetTexture(NULL);
430N/A break;
430N/A case STATE_AAPGRAMOP:
430N/A res = DisableAAParallelogramProgram();
430N/A break;
430N/A default:
430N/A break;
430N/A }
0N/A
430N/A switch (newState) {
430N/A case STATE_MASKOP:
430N/A pMaskCache->Enable();
430N/A UpdateTextureColorState(D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE);
430N/A break;
430N/A case STATE_GLYPHOP:
430N/A D3DTR_EnableGlyphVertexCache(this);
430N/A UpdateTextureColorState(D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE);
430N/A break;
430N/A case STATE_TEXTUREOP:
430N/A UpdateTextureColorState(D3DTA_TEXTURE);
430N/A break;
430N/A case STATE_AAPGRAMOP:
430N/A res = EnableAAParallelogramProgram();
430N/A break;
430N/A default:
430N/A break;
0N/A }
430N/A
430N/A opState = newState;
430N/A
430N/A return res;
430N/A}
430N/A
430N/AHRESULT D3DContext::FlushVertexQueue()
430N/A{
430N/A if (pVCacher != NULL) {
430N/A return pVCacher->Render();
430N/A }
430N/A return E_FAIL;
0N/A}
0N/A
0N/AHRESULT D3DContext::BeginScene(jbyte newState)
0N/A{
430N/A if (!pd3dDevice) {
430N/A return E_FAIL;
0N/A } else {
0N/A UpdateState(newState);
0N/A if (!bBeginScenePending) {
0N/A bBeginScenePending = TRUE;
430N/A HRESULT res = pd3dDevice->BeginScene();
0N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::BeginScene");
0N/A if (FAILED(res)) {
0N/A // this will cause context reinitialization
430N/A opState = STATE_CHANGE;
0N/A }
0N/A return res;
0N/A }
430N/A return S_OK;
0N/A }
0N/A}
0N/A
430N/AHRESULT D3DContext::EndScene() {
430N/A if (bBeginScenePending) {
430N/A FlushVertexQueue();
430N/A bBeginScenePending = FALSE;
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EndScene");
430N/A return pd3dDevice->EndScene();
430N/A }
430N/A return S_OK;
430N/A}
430N/A
430N/A/**
430N/A * Compiles and links the given fragment shader program. If
430N/A * successful, this function returns a handle to the newly created shader
430N/A * program; otherwise returns 0.
0N/A */
430N/AIDirect3DPixelShader9 *D3DContext::CreateFragmentProgram(DWORD **shaders,
430N/A ShaderList *programs,
430N/A jint flags)
0N/A{
430N/A DWORD *sourceCode;
430N/A IDirect3DPixelShader9 *pProgram;
430N/A
430N/A J2dTraceLn1(J2D_TRACE_INFO,
430N/A "D3DContext::CreateFragmentProgram: flags=%d",
430N/A flags);
0N/A
430N/A sourceCode = shaders[flags];
430N/A if (FAILED(pd3dDevice->CreatePixelShader(sourceCode, &pProgram))) {
430N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
430N/A "D3DContext::CreateFragmentProgram: error creating program");
430N/A return NULL;
0N/A }
430N/A
430N/A // add it to the cache
430N/A ShaderList_AddProgram(programs, ptr_to_jlong(pProgram),
430N/A 0 /*unused*/, 0 /*unused*/, flags);
430N/A
430N/A return pProgram;
0N/A}
0N/A
430N/A/**
430N/A * Locates and enables a fragment program given a list of shader programs
430N/A * (ShaderInfos), using this context's state and flags as search
430N/A * parameters. The "flags" parameter is a bitwise-or'd value that helps
430N/A * differentiate one program for another; the interpretation of this value
430N/A * varies depending on the type of shader (BufImgOp, Paint, etc) but here
430N/A * it is only used to find another ShaderInfo with that same "flags" value.
0N/A */
430N/AHRESULT D3DContext::EnableFragmentProgram(DWORD **shaders,
430N/A ShaderList *programList,
430N/A jint flags)
0N/A{
430N/A HRESULT res;
430N/A jlong programID;
430N/A IDirect3DPixelShader9 *pProgram;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EnableFragmentProgram");
430N/A
430N/A programID =
430N/A ShaderList_FindProgram(programList,
430N/A 0 /*unused*/, 0 /*unused*/, flags);
0N/A
430N/A pProgram = (IDirect3DPixelShader9 *)jlong_to_ptr(programID);
430N/A if (pProgram == NULL) {
430N/A pProgram = CreateFragmentProgram(shaders, programList, flags);
430N/A if (pProgram == NULL) {
430N/A return E_FAIL;
430N/A }
0N/A }
430N/A
430N/A if (FAILED(res = pd3dDevice->SetPixelShader(pProgram))) {
430N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
430N/A "D3DContext::EnableFragmentProgram: error setting pixel shader");
430N/A return res;
430N/A }
430N/A
430N/A return S_OK;
0N/A}
0N/A
430N/AHRESULT D3DContext::EnableBasicGradientProgram(jint flags)
0N/A{
430N/A return EnableFragmentProgram((DWORD **)gradShaders,
430N/A &basicGradPrograms, flags);
430N/A}
0N/A
430N/AHRESULT D3DContext::EnableLinearGradientProgram(jint flags)
430N/A{
430N/A return EnableFragmentProgram((DWORD **)linearShaders,
430N/A &linearGradPrograms, flags);
0N/A}
0N/A
430N/AHRESULT D3DContext::EnableRadialGradientProgram(jint flags)
430N/A{
430N/A return EnableFragmentProgram((DWORD **)radialShaders,
430N/A &radialGradPrograms, flags);
430N/A}
430N/A
430N/AHRESULT D3DContext::EnableConvolveProgram(jint flags)
0N/A{
430N/A return EnableFragmentProgram((DWORD **)convolveShaders,
430N/A &convolvePrograms, flags);
430N/A}
0N/A
430N/AHRESULT D3DContext::EnableRescaleProgram(jint flags)
430N/A{
430N/A return EnableFragmentProgram((DWORD **)rescaleShaders,
430N/A &rescalePrograms, flags);
430N/A}
430N/A
430N/AHRESULT D3DContext::EnableLookupProgram(jint flags)
430N/A{
430N/A return EnableFragmentProgram((DWORD **)lookupShaders,
430N/A &lookupPrograms, flags);
0N/A}
0N/A
430N/AHRESULT D3DContext::EnableLCDTextProgram()
0N/A{
430N/A HRESULT res;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EnableLCDTextProgram");
0N/A
430N/A if (lcdTextProgram == NULL) {
430N/A if (FAILED(res = pd3dDevice->CreatePixelShader(lcdtext0,
430N/A &lcdTextProgram)))
430N/A {
430N/A return res;
430N/A }
430N/A }
430N/A
430N/A if (FAILED(res = pd3dDevice->SetPixelShader(lcdTextProgram))) {
430N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
430N/A "D3DContext::EnableLCDTextProgram: error setting pixel shader");
430N/A return res;
0N/A }
0N/A
430N/A return S_OK;
430N/A}
430N/A
430N/AHRESULT D3DContext::EnableAAParallelogramProgram()
430N/A{
430N/A HRESULT res;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EnableAAParallelogramProgram");
430N/A
430N/A if (aaPgramProgram == NULL) {
430N/A if (FAILED(res = pd3dDevice->CreatePixelShader(aapgram0,
430N/A &aaPgramProgram))) {
430N/A DebugPrintD3DError(res, "D3DContext::EnableAAParallelogramProgram: "
430N/A "error creating pixel shader");
430N/A return res;
430N/A }
430N/A }
430N/A
430N/A if (FAILED(res = pd3dDevice->SetPixelShader(aaPgramProgram))) {
430N/A DebugPrintD3DError(res, "D3DContext::EnableAAParallelogramProgram: "
430N/A "error setting pixel shader");
430N/A return res;
430N/A }
430N/A
430N/A return S_OK;
0N/A}
0N/A
430N/AHRESULT D3DContext::DisableAAParallelogramProgram()
0N/A{
430N/A HRESULT res;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::DisableAAParallelogramProgram");
430N/A
430N/A if (aaPgramProgram != NULL) {
430N/A if (FAILED(res = pd3dDevice->SetPixelShader(NULL))) {
430N/A DebugPrintD3DError(res,
430N/A "D3DContext::DisableAAParallelogramProgram: "
430N/A "error clearing pixel shader");
430N/A return res;
430N/A }
430N/A }
0N/A
430N/A return S_OK;
430N/A}
430N/A
430N/ABOOL D3DContext::IsAlphaRTSurfaceSupported()
430N/A{
430N/A HRESULT res = pd3dObject->CheckDeviceFormat(adapterOrdinal,
430N/A devCaps.DeviceType,
430N/A curParams.BackBufferFormat,
430N/A D3DUSAGE_RENDERTARGET,
430N/A D3DRTYPE_SURFACE,
430N/A D3DFMT_A8R8G8B8);
430N/A return SUCCEEDED(res);
0N/A}
0N/A
430N/ABOOL D3DContext::IsAlphaRTTSupported()
0N/A{
430N/A HRESULT res = pd3dObject->CheckDeviceFormat(adapterOrdinal,
430N/A devCaps.DeviceType,
430N/A curParams.BackBufferFormat,
430N/A D3DUSAGE_RENDERTARGET,
430N/A D3DRTYPE_TEXTURE,
430N/A D3DFMT_A8R8G8B8);
430N/A return SUCCEEDED(res);
430N/A}
0N/A
430N/ABOOL D3DContext::IsOpaqueRTTSupported()
430N/A{
430N/A HRESULT res = pd3dObject->CheckDeviceFormat(adapterOrdinal,
430N/A devCaps.DeviceType,
430N/A curParams.BackBufferFormat,
430N/A D3DUSAGE_RENDERTARGET,
430N/A D3DRTYPE_TEXTURE,
430N/A curParams.BackBufferFormat);
430N/A return SUCCEEDED(res);
0N/A}
0N/A
430N/AHRESULT D3DContext::InitContextCaps() {
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DContext::InitContextCaps");
430N/A J2dTraceLn1(J2D_TRACE_VERBOSE, " caps for adapter %d :", adapterOrdinal);
430N/A
430N/A if (pd3dDevice == NULL || pd3dObject == NULL) {
430N/A contextCaps = CAPS_EMPTY;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_EMPTY");
430N/A return E_FAIL;
430N/A }
430N/A
430N/A contextCaps = CAPS_DEVICE_OK;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_DEVICE_OK");
0N/A
430N/A if (IsAlphaRTSurfaceSupported()) {
430N/A contextCaps |= CAPS_RT_PLAIN_ALPHA;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_RT_PLAIN_ALPHA");
430N/A }
430N/A if (IsAlphaRTTSupported()) {
430N/A contextCaps |= CAPS_RT_TEXTURE_ALPHA;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_RT_TEXTURE_ALPHA");
430N/A }
430N/A if (IsOpaqueRTTSupported()) {
430N/A contextCaps |= CAPS_RT_TEXTURE_OPAQUE;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_RT_TEXTURE_OPAQUE");
430N/A }
430N/A if (IsPixelShader20Supported()) {
430N/A contextCaps |= CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE,
430N/A " | CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20");
430N/A // Pre-PS3.0 video boards are very slow with the AA shader, so
430N/A // we will require PS30 hw even though the shader is compiled for 2.0a
430N/A// if (IsGradientInstructionExtensionSupported()) {
430N/A// contextCaps |= CAPS_AA_SHADER;
430N/A// J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_AA_SHADER");
430N/A// }
0N/A }
430N/A if (IsPixelShader30Supported()) {
430N/A if ((contextCaps & CAPS_AA_SHADER) == 0) {
430N/A // This flag was not already mentioned above...
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_AA_SHADER");
430N/A }
430N/A contextCaps |= CAPS_PS30 | CAPS_AA_SHADER;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_PS30");
430N/A }
430N/A if (IsMultiTexturingSupported()) {
430N/A contextCaps |= CAPS_MULTITEXTURE;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_MULTITEXTURE");
430N/A }
430N/A if (!IsPow2TexturesOnly()) {
430N/A contextCaps |= CAPS_TEXNONPOW2;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_TEXNONPOW2");
430N/A }
430N/A if (!IsSquareTexturesOnly()) {
430N/A contextCaps |= CAPS_TEXNONSQUARE;
430N/A J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_TEXNONSQUARE");
430N/A }
430N/A return S_OK;
0N/A}