1 /*
2 * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include <jlong.h>
27
28 #include "D3DBufImgOps.h"
29 #include "D3DContext.h"
30 #include "D3DRenderQueue.h"
31 #include "D3DSurfaceData.h"
32 #include "GraphicsPrimitiveMgr.h"
33
34 /**************************** ConvolveOp support ****************************/
35
36 /**
37 * The maximum kernel size supported by the ConvolveOp shader.
38 */
39 #define MAX_KERNEL_SIZE 25
40
41 HRESULT
D3DBufImgOps_EnableConvolveOp(D3DContext * d3dc,jlong pSrcOps,jboolean edgeZeroFill,jint kernelWidth,jint kernelHeight,unsigned char * kernel)42 D3DBufImgOps_EnableConvolveOp(D3DContext *d3dc, jlong pSrcOps,
43 jboolean edgeZeroFill,
44 jint kernelWidth, jint kernelHeight,
45 unsigned char *kernel)
46 {
47 HRESULT res;
48 IDirect3DDevice9 *pd3dDevice;
49 D3DSDOps *srcOps = (D3DSDOps *)jlong_to_ptr(pSrcOps);
50 jint kernelSize = kernelWidth * kernelHeight;
51 jint texW, texH;
52 jfloat xoff, yoff;
53 jfloat edgeX, edgeY;
54 jfloat imgEdge[4];
55 jfloat kernelVals[MAX_KERNEL_SIZE*4];
56 jint i, j, kIndex;
57 jint flags = 0;
58
59 J2dTraceLn2(J2D_TRACE_INFO,
60 "D3DBufImgOps_EnableConvolveOp: kernelW=%d kernelH=%d",
61 kernelWidth, kernelHeight);
62
63 RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
64 RETURN_STATUS_IF_NULL(srcOps, E_FAIL);
65
66 d3dc->UpdateState(STATE_CHANGE);
67
68 // texcoords are specified in the range [0,1], so to achieve an
69 // x/y offset of approximately one pixel we have to normalize
70 // to that range here
71 texW = srcOps->pResource->GetDesc()->Width;
72 texH = srcOps->pResource->GetDesc()->Height;
73 xoff = 1.0f / texW;
74 yoff = 1.0f / texH;
75
76 if (edgeZeroFill) {
77 flags |= CONVOLVE_EDGE_ZERO_FILL;
78 }
79 if (kernelWidth == 5 && kernelHeight == 5) {
80 flags |= CONVOLVE_5X5;
81 }
82
83 // locate/enable the shader program for the given flags
84 res = d3dc->EnableConvolveProgram(flags);
85 RETURN_STATUS_IF_FAILED(res);
86
87 // update the "uniform" image min/max values
88 // (texcoords are in the range [0,1])
89 // imgEdge[0] = imgMin.x
90 // imgEdge[1] = imgMin.y
91 // imgEdge[2] = imgMax.x
92 // imgEdge[3] = imgMax.y
93 edgeX = (kernelWidth/2) * xoff;
94 edgeY = (kernelHeight/2) * yoff;
95 imgEdge[0] = edgeX;
96 imgEdge[1] = edgeY;
97 imgEdge[2] = (((jfloat)srcOps->width) / texW) - edgeX;
98 imgEdge[3] = (((jfloat)srcOps->height) / texH) - edgeY;
99 pd3dDevice = d3dc->Get3DDevice();
100 pd3dDevice->SetPixelShaderConstantF(0, imgEdge, 1);
101
102 // update the "uniform" kernel offsets and values
103 kIndex = 0;
104 for (i = -kernelHeight/2; i < kernelHeight/2+1; i++) {
105 for (j = -kernelWidth/2; j < kernelWidth/2+1; j++) {
106 kernelVals[kIndex+0] = j*xoff;
107 kernelVals[kIndex+1] = i*yoff;
108 kernelVals[kIndex+2] = NEXT_FLOAT(kernel);
109 kernelVals[kIndex+3] = 0.0f; // unused
110 kIndex += 4;
111 }
112 }
113 return pd3dDevice->SetPixelShaderConstantF(1, kernelVals, kernelSize);
114 }
115
116 HRESULT
D3DBufImgOps_DisableConvolveOp(D3DContext * d3dc)117 D3DBufImgOps_DisableConvolveOp(D3DContext *d3dc)
118 {
119 IDirect3DDevice9 *pd3dDevice;
120
121 J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_DisableConvolveOp");
122
123 RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
124 d3dc->UpdateState(STATE_CHANGE);
125
126 // disable the ConvolveOp shader
127 pd3dDevice = d3dc->Get3DDevice();
128 return pd3dDevice->SetPixelShader(NULL);
129 }
130
131 /**************************** RescaleOp support *****************************/
132
133 HRESULT
D3DBufImgOps_EnableRescaleOp(D3DContext * d3dc,jboolean nonPremult,unsigned char * scaleFactors,unsigned char * offsets)134 D3DBufImgOps_EnableRescaleOp(D3DContext *d3dc,
135 jboolean nonPremult,
136 unsigned char *scaleFactors,
137 unsigned char *offsets)
138 {
139 HRESULT res;
140 IDirect3DDevice9 *pd3dDevice;
141 jint flags = 0;
142
143 J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_EnableRescaleOp");
144
145 RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
146
147 d3dc->UpdateState(STATE_CHANGE);
148
149 // choose the appropriate shader, depending on the source image
150 if (nonPremult) {
151 flags |= RESCALE_NON_PREMULT;
152 }
153
154 // locate/enable the shader program for the given flags
155 res = d3dc->EnableRescaleProgram(flags);
156 RETURN_STATUS_IF_FAILED(res);
157
158 // update the "uniform" scale factor values (note that the Java-level
159 // dispatching code always passes down 4 values here, regardless of
160 // the original source image type)
161 pd3dDevice = d3dc->Get3DDevice();
162 pd3dDevice->SetPixelShaderConstantF(0, (float *)scaleFactors, 1);
163
164 // update the "uniform" offset values (note that the Java-level
165 // dispatching code always passes down 4 values here, and that the
166 // offsets will have already been normalized to the range [0,1])
167 return pd3dDevice->SetPixelShaderConstantF(1, (float *)offsets, 1);
168 }
169
170 HRESULT
D3DBufImgOps_DisableRescaleOp(D3DContext * d3dc)171 D3DBufImgOps_DisableRescaleOp(D3DContext *d3dc)
172 {
173 IDirect3DDevice9 *pd3dDevice;
174
175 J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_DisableRescaleOp");
176
177 RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
178
179 d3dc->UpdateState(STATE_CHANGE);
180
181 // disable the RescaleOp shader
182 pd3dDevice = d3dc->Get3DDevice();
183 return pd3dDevice->SetPixelShader(NULL);
184 }
185
186 /**************************** LookupOp support ******************************/
187
188 HRESULT
D3DBufImgOps_EnableLookupOp(D3DContext * d3dc,jboolean nonPremult,jboolean shortData,jint numBands,jint bandLength,jint offset,void * tableValues)189 D3DBufImgOps_EnableLookupOp(D3DContext *d3dc,
190 jboolean nonPremult, jboolean shortData,
191 jint numBands, jint bandLength, jint offset,
192 void *tableValues)
193 {
194 HRESULT res;
195 IDirect3DDevice9 *pd3dDevice;
196 D3DResource *pLutTexRes;
197 IDirect3DTexture9 *pLutTex;
198 int bytesPerElem = (shortData ? 2 : 1);
199 jfloat foffsets[4];
200 void *bands[4];
201 int i;
202 jint flags = 0;
203
204 for (i = 0; i < 4; i++) {
205 bands[i] = NULL;
206 }
207 J2dTraceLn4(J2D_TRACE_INFO,
208 "D3DBufImgOps_EnableLookupOp: short=%d num=%d len=%d off=%d",
209 shortData, numBands, bandLength, offset);
210
211 RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
212
213 d3dc->UpdateState(STATE_CHANGE);
214
215 // choose the appropriate shader, depending on the source image
216 // and the number of bands involved
217 if (numBands != 4) {
218 flags |= LOOKUP_USE_SRC_ALPHA;
219 }
220 if (nonPremult) {
221 flags |= LOOKUP_NON_PREMULT;
222 }
223
224 // locate/enable the shader program for the given flags
225 res = d3dc->EnableLookupProgram(flags);
226 RETURN_STATUS_IF_FAILED(res);
227
228 // update the "uniform" offset value
229 for (i = 0; i < 4; i++) {
230 foffsets[i] = offset / 255.0f;
231 }
232 pd3dDevice = d3dc->Get3DDevice();
233 pd3dDevice->SetPixelShaderConstantF(0, foffsets, 1);
234
235 res = d3dc->GetResourceManager()->GetLookupOpLutTexture(&pLutTexRes);
236 RETURN_STATUS_IF_FAILED(res);
237 pLutTex = pLutTexRes->GetTexture();
238
239 // update the lookup table with the user-provided values
240 if (numBands == 1) {
241 // replicate the single band for R/G/B; alpha band is unused
242 for (i = 0; i < 3; i++) {
243 bands[i] = tableValues;
244 }
245 bands[3] = NULL;
246 } else if (numBands == 3) {
247 // user supplied band for each of R/G/B; alpha band is unused
248 for (i = 0; i < 3; i++) {
249 bands[i] = PtrAddBytes(tableValues, i*bandLength*bytesPerElem);
250 }
251 bands[3] = NULL;
252 } else if (numBands == 4) {
253 // user supplied band for each of R/G/B/A
254 for (i = 0; i < 4; i++) {
255 bands[i] = PtrAddBytes(tableValues, i*bandLength*bytesPerElem);
256 }
257 }
258
259 // upload the bands one row at a time into our lookup table texture
260 D3DLOCKED_RECT lockedRect;
261 res = pLutTex->LockRect(0, &lockedRect, NULL, D3DLOCK_NOSYSLOCK);
262 RETURN_STATUS_IF_FAILED(res);
263
264 jushort *pBase = (jushort*)lockedRect.pBits;
265 for (i = 0; i < 4; i++) {
266 jushort *pDst;
267 if (bands[i] == NULL) {
268 continue;
269 }
270 pDst = pBase + (i * 256);
271 if (shortData) {
272 memcpy(pDst, bands[i], bandLength*sizeof(jushort));
273 } else {
274 int j;
275 jubyte *pSrc = (jubyte *)bands[i];
276 for (j = 0; j < bandLength; j++) {
277 pDst[j] = (jushort)(pSrc[j] << 8);
278 }
279 }
280 }
281 pLutTex->UnlockRect(0);
282
283 // bind the lookup table to texture unit 1 and enable texturing
284 res = d3dc->SetTexture(pLutTex, 1);
285 pd3dDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
286 pd3dDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
287 pd3dDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
288 pd3dDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
289 return res;
290 }
291
292 HRESULT
D3DBufImgOps_DisableLookupOp(D3DContext * d3dc)293 D3DBufImgOps_DisableLookupOp(D3DContext *d3dc)
294 {
295 IDirect3DDevice9 *pd3dDevice;
296
297 J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_DisableLookupOp");
298
299 RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
300
301 d3dc->UpdateState(STATE_CHANGE);
302
303 // disable the LookupOp shader
304 pd3dDevice = d3dc->Get3DDevice();
305 pd3dDevice->SetPixelShader(NULL);
306
307 // disable the lookup table on texture unit 1
308 return d3dc->SetTexture(NULL, 1);
309 }
310