| /* | |
| * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| #include <jlong.h> | |
| #include <string.h> | |
| #include "sun_java2d_d3d_D3DPaints_MultiGradient.h" | |
| #include "D3DPaints.h" | |
| #include "D3DContext.h" | |
| #include "D3DRenderQueue.h" | |
| #include "D3DSurfaceData.h" | |
| HRESULT | |
| D3DPaints_ResetPaint(D3DContext *d3dc) | |
| { | |
| jint pixel, paintState; | |
| jubyte ea; | |
| HRESULT res; | |
| J2dTraceLn(J2D_TRACE_INFO, "D3DPaints_ResetPaint"); | |
| RETURN_STATUS_IF_NULL(d3dc, E_FAIL); | |
| paintState = d3dc->GetPaintState(); | |
| J2dTraceLn1(J2D_TRACE_VERBOSE, " state=%d", paintState); | |
| res = d3dc->UpdateState(STATE_OTHEROP); | |
| // disable current complex paint state, if necessary | |
| if (paintState > PAINT_ALPHACOLOR) { | |
| IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice(); | |
| DWORD sampler = d3dc->useMask ? 1 : 0; | |
| d3dc->SetTexture(NULL, sampler); | |
| pd3dDevice->SetSamplerState(sampler, | |
| D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); | |
| pd3dDevice->SetSamplerState(sampler, | |
| D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); | |
| pd3dDevice->SetTextureStageState(sampler, | |
| D3DTSS_TEXCOORDINDEX, sampler); | |
| res = pd3dDevice->SetTextureStageState(sampler, | |
| D3DTSS_TEXTURETRANSFORMFLAGS, | |
| D3DTTFF_DISABLE); | |
| if (paintState == PAINT_GRADIENT || | |
| paintState == PAINT_LIN_GRADIENT || | |
| paintState == PAINT_RAD_GRADIENT) | |
| { | |
| res = pd3dDevice->SetPixelShader(NULL); | |
| } | |
| } | |
| // set each component of the current color state to the extra alpha | |
| // value, which will effectively apply the extra alpha to each fragment | |
| // in paint/texturing operations | |
| ea = (jubyte)(d3dc->extraAlpha * 0xff + 0.5f); | |
| pixel = (ea << 24) | (ea << 16) | (ea << 8) | (ea << 0); | |
| d3dc->pVCacher->SetColor(pixel); | |
| d3dc->useMask = JNI_FALSE; | |
| d3dc->SetPaintState(-1); | |
| return res; | |
| } | |
| HRESULT | |
| D3DPaints_SetColor(D3DContext *d3dc, jint pixel) | |
| { | |
| HRESULT res = S_OK; | |
| J2dTraceLn1(J2D_TRACE_INFO, "D3DPaints_SetColor: pixel=%08x", pixel); | |
| RETURN_STATUS_IF_NULL(d3dc, E_FAIL); | |
| // no need to reset the current op state here unless the paint | |
| // state really needs to be changed | |
| if (d3dc->GetPaintState() > PAINT_ALPHACOLOR) { | |
| res = D3DPaints_ResetPaint(d3dc); | |
| } | |
| d3dc->pVCacher->SetColor(pixel); | |
| d3dc->useMask = JNI_FALSE; | |
| d3dc->SetPaintState(PAINT_ALPHACOLOR); | |
| return res; | |
| } | |
| /************************* GradientPaint support ****************************/ | |
| HRESULT | |
| D3DPaints_SetGradientPaint(D3DContext *d3dc, | |
| jboolean useMask, jboolean cyclic, | |
| jdouble p0, jdouble p1, jdouble p3, | |
| jint pixel1, jint pixel2) | |
| { | |
| IDirect3DDevice9 *pd3dDevice; | |
| HRESULT res; | |
| J2dTraceLn(J2D_TRACE_INFO, "D3DPaints_SetGradientPaint"); | |
| RETURN_STATUS_IF_NULL(d3dc, E_FAIL); | |
| D3DPaints_ResetPaint(d3dc); | |
| #if 0 | |
| /* | |
| * REMIND: The following code represents the original fast gradient | |
| * implementation. The problem is that it relies on LINEAR | |
| * texture filtering, which does not provide sufficient | |
| * precision on certain hardware (from ATI, notably), which | |
| * will cause visible banding (e.g. 64 shades of gray between | |
| * black and white, instead of the expected 256 shades. For | |
| * correctness on such hardware, it is necessary to use a | |
| * shader-based approach that does not suffer from these | |
| * precision issues (see below). This original implementation | |
| * is about 16x faster than software, whereas the shader-based | |
| * implementation is only about 4x faster than software (still | |
| * impressive). For simplicity, we will always use the | |
| * shader-based version for now, but in the future we could | |
| * consider using the fast path for certain hardware (that does | |
| * not exhibit the problem) or provide a flag to allow developers | |
| * to control which path we take (for those that are less | |
| * concerned about quality). Therefore, I'll leave this code | |
| * here (currently disabled) for future use. | |
| */ | |
| D3DResource *pGradientTexRes; | |
| IDirect3DTexture9 *pGradientTex; | |
| // this will initialize the gradient texture, if necessary | |
| res = d3dc->GetResourceManager()->GetGradientTexture(&pGradientTexRes); | |
| RETURN_STATUS_IF_FAILED(res); | |
| pGradientTex = pGradientTexRes->GetTexture(); | |
| // update the texture containing the gradient colors | |
| { | |
| D3DLOCKED_RECT lockedRect; | |
| res = pGradientTex->LockRect(0, &lockedRect, NULL, D3DLOCK_NOSYSLOCK); | |
| RETURN_STATUS_IF_FAILED(res); | |
| jint *pPix = (jint*)lockedRect.pBits; | |
| pPix[0] = pixel1; | |
| pPix[1] = pixel2; | |
| pGradientTex->UnlockRect(0); | |
| } | |
| DWORD sampler = useMask ? 1 : 0; | |
| DWORD wrapMode = cyclic ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP; | |
| d3dc->SetTexture(pGradientTex, sampler); | |
| d3dc->UpdateTextureColorState(D3DTA_TEXTURE, sampler); | |
| pd3dDevice = d3dc->Get3DDevice(); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_ADDRESSU, wrapMode); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_ADDRESSV, wrapMode); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); | |
| D3DMATRIX mt; | |
| ZeroMemory(&mt, sizeof(mt)); | |
| mt._11 = (float)p0; | |
| mt._21 = (float)p1; | |
| mt._31 = (float)0.0; | |
| mt._41 = (float)p3; | |
| mt._12 = 0.0f; | |
| mt._22 = 1.0f; | |
| mt._32 = 0.0f; | |
| mt._42 = 0.0f; | |
| pd3dDevice->SetTransform(useMask ? D3DTS_TEXTURE1 : D3DTS_TEXTURE0, &mt); | |
| pd3dDevice->SetTextureStageState(sampler, D3DTSS_TEXCOORDINDEX, | |
| D3DTSS_TCI_CAMERASPACEPOSITION); | |
| res = pd3dDevice->SetTextureStageState(sampler, | |
| D3DTSS_TEXTURETRANSFORMFLAGS, | |
| D3DTTFF_COUNT2); | |
| #else | |
| jfloat params[4]; | |
| jfloat color[4]; | |
| jint flags = 0; | |
| if (cyclic) flags |= BASIC_GRAD_IS_CYCLIC; | |
| if (useMask) flags |= BASIC_GRAD_USE_MASK; | |
| // locate/enable the shader program for the given flags | |
| res = d3dc->EnableBasicGradientProgram(flags); | |
| RETURN_STATUS_IF_FAILED(res); | |
| // update the "uniform" values | |
| params[0] = (jfloat)p0; | |
| params[1] = (jfloat)p1; | |
| params[2] = (jfloat)p3; | |
| params[3] = 0.0f; // unused | |
| pd3dDevice = d3dc->Get3DDevice(); | |
| res = pd3dDevice->SetPixelShaderConstantF(0, params, 1); | |
| color[0] = ((pixel1 >> 16) & 0xff) / 255.0f; // r | |
| color[1] = ((pixel1 >> 8) & 0xff) / 255.0f; // g | |
| color[2] = ((pixel1 >> 0) & 0xff) / 255.0f; // b | |
| color[3] = ((pixel1 >> 24) & 0xff) / 255.0f; // a | |
| res = pd3dDevice->SetPixelShaderConstantF(1, color, 1); | |
| color[0] = ((pixel2 >> 16) & 0xff) / 255.0f; // r | |
| color[1] = ((pixel2 >> 8) & 0xff) / 255.0f; // g | |
| color[2] = ((pixel2 >> 0) & 0xff) / 255.0f; // b | |
| color[3] = ((pixel2 >> 24) & 0xff) / 255.0f; // a | |
| res = pd3dDevice->SetPixelShaderConstantF(2, color, 1); | |
| // set up texture coordinate transform with identity matrix, which | |
| // will have the effect of passing the current window-space coordinates | |
| // through to the TEXCOORD0/1 register used by the basic gradient | |
| // pixel shader | |
| DWORD sampler = useMask ? 1 : 0; | |
| D3DMATRIX mt; | |
| ZeroMemory(&mt, sizeof(mt)); | |
| mt._11 = 1.0f; | |
| mt._21 = 0.0f; | |
| mt._31 = 0.0f; | |
| mt._41 = 0.0f; | |
| mt._12 = 0.0f; | |
| mt._22 = 1.0f; | |
| mt._32 = 0.0f; | |
| mt._42 = 0.0f; | |
| pd3dDevice->SetTransform(useMask ? D3DTS_TEXTURE1 : D3DTS_TEXTURE0, &mt); | |
| pd3dDevice->SetTextureStageState(sampler, D3DTSS_TEXCOORDINDEX, | |
| D3DTSS_TCI_CAMERASPACEPOSITION); | |
| pd3dDevice->SetTextureStageState(sampler, D3DTSS_TEXTURETRANSFORMFLAGS, | |
| D3DTTFF_COUNT2); | |
| #endif | |
| // pixel state has been set appropriately in D3DPaints_ResetPaint() | |
| d3dc->useMask = useMask; | |
| d3dc->SetPaintState(PAINT_GRADIENT); | |
| return res; | |
| } | |
| /************************** TexturePaint support ****************************/ | |
| HRESULT | |
| D3DPaints_SetTexturePaint(D3DContext *d3dc, | |
| jboolean useMask, | |
| jlong pSrcOps, jboolean filter, | |
| jdouble xp0, jdouble xp1, jdouble xp3, | |
| jdouble yp0, jdouble yp1, jdouble yp3) | |
| { | |
| D3DSDOps *srcOps = (D3DSDOps *)jlong_to_ptr(pSrcOps); | |
| IDirect3DDevice9 *pd3dDevice; | |
| HRESULT res; | |
| J2dTraceLn(J2D_TRACE_INFO, "D3DPaints_SetTexturePaint"); | |
| RETURN_STATUS_IF_NULL(d3dc, E_FAIL); | |
| RETURN_STATUS_IF_NULL(srcOps, E_FAIL); | |
| RETURN_STATUS_IF_NULL(srcOps->pResource, E_FAIL); | |
| D3DPaints_ResetPaint(d3dc); | |
| DWORD sampler = useMask ? 1 : 0; | |
| DWORD dwFilter = filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; | |
| res = d3dc->SetTexture(srcOps->pResource->GetTexture(), sampler); | |
| d3dc->UpdateTextureColorState(D3DTA_TEXTURE, sampler); | |
| pd3dDevice = d3dc->Get3DDevice(); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_MAGFILTER, dwFilter); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_MINFILTER, dwFilter); | |
| D3DMATRIX mt; | |
| ZeroMemory(&mt, sizeof(mt)); | |
| // offset by a half texel to correctly map texels to pixels | |
| // m02 = tx * m00 + ty * m01 + m02; | |
| // m12 = tx * m10 + ty * m11 + m12; | |
| jdouble tx = (1 / (2.0f * srcOps->pResource->GetDesc()->Width)); | |
| jdouble ty = (1 / (2.0f * srcOps->pResource->GetDesc()->Height)); | |
| xp3 = tx * xp0 + ty * xp1 + xp3; | |
| yp3 = tx * yp0 + ty * yp1 + yp3; | |
| mt._11 = (float)xp0; | |
| mt._21 = (float)xp1; | |
| mt._31 = (float)0.0; | |
| mt._41 = (float)xp3; | |
| mt._12 = (float)yp0; | |
| mt._22 = (float)yp1; | |
| mt._32 = (float)0.0; | |
| mt._42 = (float)yp3; | |
| pd3dDevice->SetTransform(useMask ? D3DTS_TEXTURE1 : D3DTS_TEXTURE0, &mt); | |
| pd3dDevice->SetTextureStageState(sampler, D3DTSS_TEXCOORDINDEX, | |
| D3DTSS_TCI_CAMERASPACEPOSITION); | |
| pd3dDevice->SetTextureStageState(sampler, D3DTSS_TEXTURETRANSFORMFLAGS, | |
| D3DTTFF_COUNT2); | |
| // pixel state has been set appropriately in D3DPaints_ResetPaint() | |
| d3dc->useMask = useMask; | |
| d3dc->SetPaintState(PAINT_TEXTURE); | |
| return res; | |
| } | |
| /****************** Shared MultipleGradientPaint support ********************/ | |
| /** Composes the given parameters as flags into the given flags variable.*/ | |
| #define COMPOSE_FLAGS(flags, cycleMethod, large, useMask, linear) \ | |
| do { \ | |
| flags |= ((cycleMethod) & MULTI_GRAD_CYCLE_METHOD); \ | |
| if (large) flags |= MULTI_GRAD_LARGE; \ | |
| if (useMask) flags |= MULTI_GRAD_USE_MASK; \ | |
| if (linear) flags |= MULTI_GRAD_LINEAR_RGB; \ | |
| } while (0) | |
| /** | |
| * The maximum number of gradient "stops" supported by the fragment shader | |
| * and related code. When the MULTI_GRAD_LARGE flag is set, we will use | |
| * MAX_FRACTIONS_LARGE; otherwise, we use MAX_FRACTIONS_SMALL. By having | |
| * two separate values, we can have one highly optimized shader (SMALL) that | |
| * supports only a few fractions/colors, and then another, less optimal | |
| * shader that supports more stops. | |
| */ | |
| #define MAX_FRACTIONS \ | |
| sun_java2d_d3d_D3DPaints_MultiGradient_MULTI_MAX_FRACTIONS_D3D | |
| #define MAX_FRACTIONS_LARGE MAX_FRACTIONS | |
| #define MAX_FRACTIONS_SMALL 4 | |
| /** | |
| * Called from the D3DPaints_SetLinear/RadialGradientPaint() methods | |
| * in order to setup the fraction/color values that are common to both. | |
| */ | |
| static HRESULT | |
| D3DPaints_SetMultiGradientPaint(D3DContext *d3dc, | |
| jboolean useMask, jint numStops, | |
| void *pFractions, void *pPixels) | |
| { | |
| HRESULT res; | |
| IDirect3DDevice9 *pd3dDevice; | |
| IDirect3DTexture9 *pMultiGradientTex; | |
| D3DResource *pMultiGradientTexRes; | |
| jint maxFractions = (numStops > MAX_FRACTIONS_SMALL) ? | |
| MAX_FRACTIONS_LARGE : MAX_FRACTIONS_SMALL; | |
| jfloat stopVals[MAX_FRACTIONS * 4]; | |
| jfloat *fractions = (jfloat *)pFractions; | |
| juint *pixels = (juint *)pPixels; | |
| int i; | |
| int fIndex = 0; | |
| pd3dDevice = d3dc->Get3DDevice(); | |
| // update the "uniform" fractions and scale factors | |
| for (i = 0; i < maxFractions; i++) { | |
| stopVals[fIndex+0] = (i < numStops) ? | |
| fractions[i] : 0.0f; | |
| stopVals[fIndex+1] = (i < numStops-1) ? | |
| 1.0f / (fractions[i+1] - fractions[i]) : 0.0f; | |
| stopVals[fIndex+2] = 0.0f; // unused | |
| stopVals[fIndex+3] = 0.0f; // unused | |
| fIndex += 4; | |
| } | |
| pd3dDevice->SetPixelShaderConstantF(0, stopVals, maxFractions); | |
| // this will initialize the multi-gradient texture, if necessary | |
| res = d3dc->GetResourceManager()-> | |
| GetMultiGradientTexture(&pMultiGradientTexRes); | |
| RETURN_STATUS_IF_FAILED(res); | |
| pMultiGradientTex = pMultiGradientTexRes->GetTexture(); | |
| // update the texture containing the gradient colors | |
| D3DLOCKED_RECT lockedRect; | |
| res = pMultiGradientTex->LockRect(0, &lockedRect, NULL, D3DLOCK_NOSYSLOCK); | |
| RETURN_STATUS_IF_FAILED(res); | |
| juint *pPix = (juint*)lockedRect.pBits; | |
| memcpy(pPix, pixels, numStops*sizeof(juint)); | |
| if (numStops < MAX_MULTI_GRADIENT_COLORS) { | |
| // when we don't have enough colors to fill the entire | |
| // color gradient, we have to replicate the last color | |
| // in the right-most texel for the NO_CYCLE case where the | |
| // texcoord is sometimes forced to 1.0 | |
| pPix[MAX_MULTI_GRADIENT_COLORS-1] = pixels[numStops-1]; | |
| } | |
| pMultiGradientTex->UnlockRect(0); | |
| // set the gradient texture and update relevant state | |
| DWORD sampler = useMask ? 1 : 0; | |
| res = d3dc->SetTexture(pMultiGradientTex, sampler); | |
| d3dc->UpdateTextureColorState(D3DTA_TEXTURE, sampler); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); | |
| pd3dDevice->SetSamplerState(sampler, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); | |
| // set up texture coordinate transform with identity matrix, which | |
| // will have the effect of passing the current window-space coordinates | |
| // through to the TEXCOORD0/1 register used by the multi-stop | |
| // gradient pixel shader | |
| D3DMATRIX mt; | |
| ZeroMemory(&mt, sizeof(mt)); | |
| mt._11 = 1.0f; | |
| mt._21 = 0.0f; | |
| mt._31 = 0.0f; | |
| mt._41 = 0.0f; | |
| mt._12 = 0.0f; | |
| mt._22 = 1.0f; | |
| mt._32 = 0.0f; | |
| mt._42 = 0.0f; | |
| pd3dDevice->SetTransform(useMask ? D3DTS_TEXTURE1 : D3DTS_TEXTURE0, &mt); | |
| pd3dDevice->SetTextureStageState(sampler, D3DTSS_TEXCOORDINDEX, | |
| D3DTSS_TCI_CAMERASPACEPOSITION); | |
| pd3dDevice->SetTextureStageState(sampler, D3DTSS_TEXTURETRANSFORMFLAGS, | |
| D3DTTFF_COUNT2); | |
| return res; | |
| } | |
| /********************** LinearGradientPaint support *************************/ | |
| HRESULT | |
| D3DPaints_SetLinearGradientPaint(D3DContext *d3dc, D3DSDOps *dstOps, | |
| jboolean useMask, jboolean linear, | |
| jint cycleMethod, jint numStops, | |
| jfloat p0, jfloat p1, jfloat p3, | |
| void *fractions, void *pixels) | |
| { | |
| HRESULT res; | |
| IDirect3DDevice9 *pd3dDevice; | |
| jfloat params[4]; | |
| jboolean large = (numStops > MAX_FRACTIONS_SMALL); | |
| jint flags = 0; | |
| J2dTraceLn(J2D_TRACE_INFO, "D3DPaints_SetLinearGradientPaint"); | |
| RETURN_STATUS_IF_NULL(d3dc, E_FAIL); | |
| RETURN_STATUS_IF_NULL(dstOps, E_FAIL); | |
| D3DPaints_ResetPaint(d3dc); | |
| COMPOSE_FLAGS(flags, cycleMethod, large, useMask, linear); | |
| // locate/enable the shader program for the given flags | |
| res = d3dc->EnableLinearGradientProgram(flags); | |
| RETURN_STATUS_IF_FAILED(res); | |
| // update the common "uniform" values (fractions and colors) | |
| D3DPaints_SetMultiGradientPaint(d3dc, useMask, | |
| numStops, fractions, pixels); | |
| // update the other "uniform" values | |
| params[0] = p0; | |
| params[1] = p1; | |
| params[2] = p3; | |
| params[3] = 0.0f; // unused | |
| pd3dDevice = d3dc->Get3DDevice(); | |
| res = pd3dDevice->SetPixelShaderConstantF(16, params, 1); | |
| // pixel state has been set appropriately in D3DPaints_ResetPaint() | |
| d3dc->useMask = useMask; | |
| d3dc->SetPaintState(PAINT_LIN_GRADIENT); | |
| return res; | |
| } | |
| /********************** RadialGradientPaint support *************************/ | |
| HRESULT | |
| D3DPaints_SetRadialGradientPaint(D3DContext *d3dc, D3DSDOps *dstOps, | |
| jboolean useMask, jboolean linear, | |
| jint cycleMethod, jint numStops, | |
| jfloat m00, jfloat m01, jfloat m02, | |
| jfloat m10, jfloat m11, jfloat m12, | |
| jfloat focusX, | |
| void *fractions, void *pixels) | |
| { | |
| HRESULT res; | |
| IDirect3DDevice9 *pd3dDevice; | |
| jfloat denom, inv_denom; | |
| jfloat params[4]; | |
| jboolean large = (numStops > MAX_FRACTIONS_SMALL); | |
| jint flags = 0; | |
| J2dTraceLn(J2D_TRACE_INFO, "D3DPaints_SetRadialGradientPaint"); | |
| RETURN_STATUS_IF_NULL(d3dc, E_FAIL); | |
| RETURN_STATUS_IF_NULL(dstOps, E_FAIL); | |
| D3DPaints_ResetPaint(d3dc); | |
| COMPOSE_FLAGS(flags, cycleMethod, large, useMask, linear); | |
| // locate/enable the shader program for the given flags | |
| res = d3dc->EnableRadialGradientProgram(flags); | |
| RETURN_STATUS_IF_FAILED(res); | |
| // update the common "uniform" values (fractions and colors) | |
| D3DPaints_SetMultiGradientPaint(d3dc, useMask, | |
| numStops, fractions, pixels); | |
| // update the other "uniform" values | |
| params[0] = m00; | |
| params[1] = m01; | |
| params[2] = m02; | |
| params[3] = 0.0f; // unused | |
| pd3dDevice = d3dc->Get3DDevice(); | |
| pd3dDevice->SetPixelShaderConstantF(16, params, 1); | |
| params[0] = m10; | |
| params[1] = m11; | |
| params[2] = m12; | |
| params[3] = 0.0f; // unused | |
| pd3dDevice->SetPixelShaderConstantF(17, params, 1); | |
| // pack a few unrelated, precalculated values into a single float4 | |
| denom = 1.0f - (focusX * focusX); | |
| inv_denom = 1.0f / denom; | |
| params[0] = focusX; | |
| params[1] = denom; | |
| params[2] = inv_denom; | |
| params[3] = 0.0f; // unused | |
| res = pd3dDevice->SetPixelShaderConstantF(18, params, 1); | |
| // pixel state has been set appropriately in D3DPaints_ResetPaint() | |
| d3dc->useMask = useMask; | |
| d3dc->SetPaintState(PAINT_RAD_GRADIENT); | |
| return res; | |
| } |