| /* |
| * 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; |
| } |