1 | /* |
2 | * Copyright (c) 2005, 2012, 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 | #ifndef HEADLESS |
27 | |
28 | #include <stdlib.h> |
29 | |
30 | #include "sun_java2d_pipe_BufferedOpCodes.h" |
31 | |
32 | #include "jlong.h" |
33 | #include "OGLBlitLoops.h" |
34 | #include "OGLBufImgOps.h" |
35 | #include "OGLContext.h" |
36 | #include "OGLMaskBlit.h" |
37 | #include "OGLMaskFill.h" |
38 | #include "OGLPaints.h" |
39 | #include "OGLRenderQueue.h" |
40 | #include "OGLRenderer.h" |
41 | #include "OGLSurfaceData.h" |
42 | #include "OGLTextRenderer.h" |
43 | #include "OGLVertexCache.h" |
44 | |
45 | /** |
46 | * Used to track whether we are in a series of a simple primitive operations |
47 | * or texturing operations. This variable should be controlled only via |
48 | * the INIT/CHECK/RESET_PREVIOUS_OP() macros. See the |
49 | * OGLRenderQueue_CheckPreviousOp() method below for more information. |
50 | */ |
51 | jint previousOp; |
52 | |
53 | /** |
54 | * References to the "current" context and destination surface. |
55 | */ |
56 | static OGLContext *oglc = NULL; |
57 | static OGLSDOps *dstOps = NULL; |
58 | |
59 | /** |
60 | * The following methods are implemented in the windowing system (i.e. GLX |
61 | * and WGL) source files. |
62 | */ |
63 | extern OGLContext *OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo); |
64 | extern void OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo); |
65 | extern void OGLSD_SwapBuffers(JNIEnv *env, jlong window); |
66 | extern void OGLSD_Flush(JNIEnv *env); |
67 | |
68 | JNIEXPORT void JNICALL |
69 | Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer |
70 | (JNIEnv *env, jobject oglrq, |
71 | jlong buf, jint limit) |
72 | { |
73 | jboolean sync = JNI_FALSE; |
74 | unsigned char *b, *end; |
75 | |
76 | J2dTraceLn1(J2D_TRACE_INFO, |
77 | "OGLRenderQueue_flushBuffer: limit=%d" , limit); |
78 | |
79 | b = (unsigned char *)jlong_to_ptr(buf); |
80 | if (b == NULL) { |
81 | J2dRlsTraceLn(J2D_TRACE_ERROR, |
82 | "OGLRenderQueue_flushBuffer: cannot get direct buffer address" ); |
83 | return; |
84 | } |
85 | |
86 | INIT_PREVIOUS_OP(); |
87 | end = b + limit; |
88 | |
89 | while (b < end) { |
90 | jint opcode = NEXT_INT(b); |
91 | |
92 | J2dTraceLn2(J2D_TRACE_VERBOSE, |
93 | "OGLRenderQueue_flushBuffer: opcode=%d, rem=%d" , |
94 | opcode, (end-b)); |
95 | |
96 | switch (opcode) { |
97 | |
98 | // draw ops |
99 | case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE: |
100 | { |
101 | jint x1 = NEXT_INT(b); |
102 | jint y1 = NEXT_INT(b); |
103 | jint x2 = NEXT_INT(b); |
104 | jint y2 = NEXT_INT(b); |
105 | OGLRenderer_DrawLine(oglc, x1, y1, x2, y2); |
106 | } |
107 | break; |
108 | case sun_java2d_pipe_BufferedOpCodes_DRAW_RECT: |
109 | { |
110 | jint x = NEXT_INT(b); |
111 | jint y = NEXT_INT(b); |
112 | jint w = NEXT_INT(b); |
113 | jint h = NEXT_INT(b); |
114 | OGLRenderer_DrawRect(oglc, x, y, w, h); |
115 | } |
116 | break; |
117 | case sun_java2d_pipe_BufferedOpCodes_DRAW_POLY: |
118 | { |
119 | jint nPoints = NEXT_INT(b); |
120 | jboolean isClosed = NEXT_BOOLEAN(b); |
121 | jint transX = NEXT_INT(b); |
122 | jint transY = NEXT_INT(b); |
123 | jint *xPoints = (jint *)b; |
124 | jint *yPoints = ((jint *)b) + nPoints; |
125 | OGLRenderer_DrawPoly(oglc, nPoints, isClosed, |
126 | transX, transY, |
127 | xPoints, yPoints); |
128 | SKIP_BYTES(b, nPoints * BYTES_PER_POLY_POINT); |
129 | } |
130 | break; |
131 | case sun_java2d_pipe_BufferedOpCodes_DRAW_PIXEL: |
132 | { |
133 | jint x = NEXT_INT(b); |
134 | jint y = NEXT_INT(b); |
135 | // Note that we could use GL_POINTS here, but the common |
136 | // use case for DRAW_PIXEL is when rendering a Path2D, |
137 | // which will consist of a mix of DRAW_PIXEL and DRAW_LINE |
138 | // calls. So to improve batching we use GL_LINES here, |
139 | // even though it requires an extra vertex per pixel. |
140 | CONTINUE_IF_NULL(oglc); |
141 | CHECK_PREVIOUS_OP(GL_LINES); |
142 | j2d_glVertex2i(x, y); |
143 | j2d_glVertex2i(x+1, y+1); |
144 | } |
145 | break; |
146 | case sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES: |
147 | { |
148 | jint count = NEXT_INT(b); |
149 | OGLRenderer_DrawScanlines(oglc, count, (jint *)b); |
150 | SKIP_BYTES(b, count * BYTES_PER_SCANLINE); |
151 | } |
152 | break; |
153 | case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM: |
154 | { |
155 | jfloat x11 = NEXT_FLOAT(b); |
156 | jfloat y11 = NEXT_FLOAT(b); |
157 | jfloat dx21 = NEXT_FLOAT(b); |
158 | jfloat dy21 = NEXT_FLOAT(b); |
159 | jfloat dx12 = NEXT_FLOAT(b); |
160 | jfloat dy12 = NEXT_FLOAT(b); |
161 | jfloat lwr21 = NEXT_FLOAT(b); |
162 | jfloat lwr12 = NEXT_FLOAT(b); |
163 | OGLRenderer_DrawParallelogram(oglc, |
164 | x11, y11, |
165 | dx21, dy21, |
166 | dx12, dy12, |
167 | lwr21, lwr12); |
168 | } |
169 | break; |
170 | case sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM: |
171 | { |
172 | jfloat x11 = NEXT_FLOAT(b); |
173 | jfloat y11 = NEXT_FLOAT(b); |
174 | jfloat dx21 = NEXT_FLOAT(b); |
175 | jfloat dy21 = NEXT_FLOAT(b); |
176 | jfloat dx12 = NEXT_FLOAT(b); |
177 | jfloat dy12 = NEXT_FLOAT(b); |
178 | jfloat lwr21 = NEXT_FLOAT(b); |
179 | jfloat lwr12 = NEXT_FLOAT(b); |
180 | OGLRenderer_DrawAAParallelogram(oglc, dstOps, |
181 | x11, y11, |
182 | dx21, dy21, |
183 | dx12, dy12, |
184 | lwr21, lwr12); |
185 | } |
186 | break; |
187 | |
188 | // fill ops |
189 | case sun_java2d_pipe_BufferedOpCodes_FILL_RECT: |
190 | { |
191 | jint x = NEXT_INT(b); |
192 | jint y = NEXT_INT(b); |
193 | jint w = NEXT_INT(b); |
194 | jint h = NEXT_INT(b); |
195 | OGLRenderer_FillRect(oglc, x, y, w, h); |
196 | } |
197 | break; |
198 | case sun_java2d_pipe_BufferedOpCodes_FILL_SPANS: |
199 | { |
200 | jint count = NEXT_INT(b); |
201 | OGLRenderer_FillSpans(oglc, count, (jint *)b); |
202 | SKIP_BYTES(b, count * BYTES_PER_SPAN); |
203 | } |
204 | break; |
205 | case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM: |
206 | { |
207 | jfloat x11 = NEXT_FLOAT(b); |
208 | jfloat y11 = NEXT_FLOAT(b); |
209 | jfloat dx21 = NEXT_FLOAT(b); |
210 | jfloat dy21 = NEXT_FLOAT(b); |
211 | jfloat dx12 = NEXT_FLOAT(b); |
212 | jfloat dy12 = NEXT_FLOAT(b); |
213 | OGLRenderer_FillParallelogram(oglc, |
214 | x11, y11, |
215 | dx21, dy21, |
216 | dx12, dy12); |
217 | } |
218 | break; |
219 | case sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM: |
220 | { |
221 | jfloat x11 = NEXT_FLOAT(b); |
222 | jfloat y11 = NEXT_FLOAT(b); |
223 | jfloat dx21 = NEXT_FLOAT(b); |
224 | jfloat dy21 = NEXT_FLOAT(b); |
225 | jfloat dx12 = NEXT_FLOAT(b); |
226 | jfloat dy12 = NEXT_FLOAT(b); |
227 | OGLRenderer_FillAAParallelogram(oglc, dstOps, |
228 | x11, y11, |
229 | dx21, dy21, |
230 | dx12, dy12); |
231 | } |
232 | break; |
233 | |
234 | // text-related ops |
235 | case sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST: |
236 | { |
237 | jint numGlyphs = NEXT_INT(b); |
238 | jint packedParams = NEXT_INT(b); |
239 | jfloat glyphListOrigX = NEXT_FLOAT(b); |
240 | jfloat glyphListOrigY = NEXT_FLOAT(b); |
241 | jboolean usePositions = EXTRACT_BOOLEAN(packedParams, |
242 | OFFSET_POSITIONS); |
243 | jboolean subPixPos = EXTRACT_BOOLEAN(packedParams, |
244 | OFFSET_SUBPIXPOS); |
245 | jboolean rgbOrder = EXTRACT_BOOLEAN(packedParams, |
246 | OFFSET_RGBORDER); |
247 | jint lcdContrast = EXTRACT_BYTE(packedParams, |
248 | OFFSET_CONTRAST); |
249 | unsigned char *images = b; |
250 | unsigned char *positions; |
251 | jint bytesPerGlyph; |
252 | if (usePositions) { |
253 | positions = (b + numGlyphs * BYTES_PER_GLYPH_IMAGE); |
254 | bytesPerGlyph = BYTES_PER_POSITIONED_GLYPH; |
255 | } else { |
256 | positions = NULL; |
257 | bytesPerGlyph = BYTES_PER_GLYPH_IMAGE; |
258 | } |
259 | OGLTR_DrawGlyphList(env, oglc, dstOps, |
260 | numGlyphs, usePositions, |
261 | subPixPos, rgbOrder, lcdContrast, |
262 | glyphListOrigX, glyphListOrigY, |
263 | images, positions); |
264 | SKIP_BYTES(b, numGlyphs * bytesPerGlyph); |
265 | } |
266 | break; |
267 | |
268 | // copy-related ops |
269 | case sun_java2d_pipe_BufferedOpCodes_COPY_AREA: |
270 | { |
271 | jint x = NEXT_INT(b); |
272 | jint y = NEXT_INT(b); |
273 | jint w = NEXT_INT(b); |
274 | jint h = NEXT_INT(b); |
275 | jint dx = NEXT_INT(b); |
276 | jint dy = NEXT_INT(b); |
277 | OGLBlitLoops_CopyArea(env, oglc, dstOps, |
278 | x, y, w, h, dx, dy); |
279 | } |
280 | break; |
281 | case sun_java2d_pipe_BufferedOpCodes_BLIT: |
282 | { |
283 | jint packedParams = NEXT_INT(b); |
284 | jint sx1 = NEXT_INT(b); |
285 | jint sy1 = NEXT_INT(b); |
286 | jint sx2 = NEXT_INT(b); |
287 | jint sy2 = NEXT_INT(b); |
288 | jdouble dx1 = NEXT_DOUBLE(b); |
289 | jdouble dy1 = NEXT_DOUBLE(b); |
290 | jdouble dx2 = NEXT_DOUBLE(b); |
291 | jdouble dy2 = NEXT_DOUBLE(b); |
292 | jlong pSrc = NEXT_LONG(b); |
293 | jlong pDst = NEXT_LONG(b); |
294 | jint hint = EXTRACT_BYTE(packedParams, OFFSET_HINT); |
295 | jboolean texture = EXTRACT_BOOLEAN(packedParams, |
296 | OFFSET_TEXTURE); |
297 | jboolean rtt = EXTRACT_BOOLEAN(packedParams, |
298 | OFFSET_RTT); |
299 | jboolean xform = EXTRACT_BOOLEAN(packedParams, |
300 | OFFSET_XFORM); |
301 | jboolean isoblit = EXTRACT_BOOLEAN(packedParams, |
302 | OFFSET_ISOBLIT); |
303 | if (isoblit) { |
304 | OGLBlitLoops_IsoBlit(env, oglc, pSrc, pDst, |
305 | xform, hint, texture, rtt, |
306 | sx1, sy1, sx2, sy2, |
307 | dx1, dy1, dx2, dy2); |
308 | } else { |
309 | jint srctype = EXTRACT_BYTE(packedParams, OFFSET_SRCTYPE); |
310 | OGLBlitLoops_Blit(env, oglc, pSrc, pDst, |
311 | xform, hint, srctype, texture, |
312 | sx1, sy1, sx2, sy2, |
313 | dx1, dy1, dx2, dy2); |
314 | } |
315 | } |
316 | break; |
317 | case sun_java2d_pipe_BufferedOpCodes_SURFACE_TO_SW_BLIT: |
318 | { |
319 | jint sx = NEXT_INT(b); |
320 | jint sy = NEXT_INT(b); |
321 | jint dx = NEXT_INT(b); |
322 | jint dy = NEXT_INT(b); |
323 | jint w = NEXT_INT(b); |
324 | jint h = NEXT_INT(b); |
325 | jint dsttype = NEXT_INT(b); |
326 | jlong pSrc = NEXT_LONG(b); |
327 | jlong pDst = NEXT_LONG(b); |
328 | OGLBlitLoops_SurfaceToSwBlit(env, oglc, |
329 | pSrc, pDst, dsttype, |
330 | sx, sy, dx, dy, w, h); |
331 | } |
332 | break; |
333 | case sun_java2d_pipe_BufferedOpCodes_MASK_FILL: |
334 | { |
335 | jint x = NEXT_INT(b); |
336 | jint y = NEXT_INT(b); |
337 | jint w = NEXT_INT(b); |
338 | jint h = NEXT_INT(b); |
339 | jint maskoff = NEXT_INT(b); |
340 | jint maskscan = NEXT_INT(b); |
341 | jint masklen = NEXT_INT(b); |
342 | unsigned char *pMask = (masklen > 0) ? b : NULL; |
343 | OGLMaskFill_MaskFill(oglc, x, y, w, h, |
344 | maskoff, maskscan, masklen, pMask); |
345 | SKIP_BYTES(b, masklen); |
346 | } |
347 | break; |
348 | case sun_java2d_pipe_BufferedOpCodes_MASK_BLIT: |
349 | { |
350 | jint dstx = NEXT_INT(b); |
351 | jint dsty = NEXT_INT(b); |
352 | jint width = NEXT_INT(b); |
353 | jint height = NEXT_INT(b); |
354 | jint masklen = width * height * sizeof(jint); |
355 | OGLMaskBlit_MaskBlit(env, oglc, |
356 | dstx, dsty, width, height, b); |
357 | SKIP_BYTES(b, masklen); |
358 | } |
359 | break; |
360 | |
361 | // state-related ops |
362 | case sun_java2d_pipe_BufferedOpCodes_SET_RECT_CLIP: |
363 | { |
364 | jint x1 = NEXT_INT(b); |
365 | jint y1 = NEXT_INT(b); |
366 | jint x2 = NEXT_INT(b); |
367 | jint y2 = NEXT_INT(b); |
368 | OGLContext_SetRectClip(oglc, dstOps, x1, y1, x2, y2); |
369 | } |
370 | break; |
371 | case sun_java2d_pipe_BufferedOpCodes_BEGIN_SHAPE_CLIP: |
372 | { |
373 | OGLContext_BeginShapeClip(oglc); |
374 | } |
375 | break; |
376 | case sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS: |
377 | { |
378 | jint count = NEXT_INT(b); |
379 | OGLRenderer_FillSpans(oglc, count, (jint *)b); |
380 | SKIP_BYTES(b, count * BYTES_PER_SPAN); |
381 | } |
382 | break; |
383 | case sun_java2d_pipe_BufferedOpCodes_END_SHAPE_CLIP: |
384 | { |
385 | OGLContext_EndShapeClip(oglc, dstOps); |
386 | } |
387 | break; |
388 | case sun_java2d_pipe_BufferedOpCodes_RESET_CLIP: |
389 | { |
390 | OGLContext_ResetClip(oglc); |
391 | } |
392 | break; |
393 | case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE: |
394 | { |
395 | jint rule = NEXT_INT(b); |
396 | jfloat extraAlpha = NEXT_FLOAT(b); |
397 | jint flags = NEXT_INT(b); |
398 | OGLContext_SetAlphaComposite(oglc, rule, extraAlpha, flags); |
399 | } |
400 | break; |
401 | case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE: |
402 | { |
403 | jint xorPixel = NEXT_INT(b); |
404 | OGLContext_SetXorComposite(oglc, xorPixel); |
405 | } |
406 | break; |
407 | case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE: |
408 | { |
409 | OGLContext_ResetComposite(oglc); |
410 | } |
411 | break; |
412 | case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM: |
413 | { |
414 | jdouble m00 = NEXT_DOUBLE(b); |
415 | jdouble m10 = NEXT_DOUBLE(b); |
416 | jdouble m01 = NEXT_DOUBLE(b); |
417 | jdouble m11 = NEXT_DOUBLE(b); |
418 | jdouble m02 = NEXT_DOUBLE(b); |
419 | jdouble m12 = NEXT_DOUBLE(b); |
420 | OGLContext_SetTransform(oglc, m00, m10, m01, m11, m02, m12); |
421 | } |
422 | break; |
423 | case sun_java2d_pipe_BufferedOpCodes_RESET_TRANSFORM: |
424 | { |
425 | OGLContext_ResetTransform(oglc); |
426 | } |
427 | break; |
428 | |
429 | // context-related ops |
430 | case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES: |
431 | { |
432 | jlong pSrc = NEXT_LONG(b); |
433 | jlong pDst = NEXT_LONG(b); |
434 | if (oglc != NULL) { |
435 | RESET_PREVIOUS_OP(); |
436 | } |
437 | oglc = OGLContext_SetSurfaces(env, pSrc, pDst); |
438 | dstOps = (OGLSDOps *)jlong_to_ptr(pDst); |
439 | } |
440 | break; |
441 | case sun_java2d_pipe_BufferedOpCodes_SET_SCRATCH_SURFACE: |
442 | { |
443 | jlong pConfigInfo = NEXT_LONG(b); |
444 | if (oglc != NULL) { |
445 | RESET_PREVIOUS_OP(); |
446 | } |
447 | oglc = OGLSD_SetScratchSurface(env, pConfigInfo); |
448 | dstOps = NULL; |
449 | } |
450 | break; |
451 | case sun_java2d_pipe_BufferedOpCodes_FLUSH_SURFACE: |
452 | { |
453 | jlong pData = NEXT_LONG(b); |
454 | OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); |
455 | if (oglsdo != NULL) { |
456 | CONTINUE_IF_NULL(oglc); |
457 | RESET_PREVIOUS_OP(); |
458 | OGLSD_Delete(env, oglsdo); |
459 | } |
460 | } |
461 | break; |
462 | case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE: |
463 | { |
464 | jlong pData = NEXT_LONG(b); |
465 | OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); |
466 | if (oglsdo != NULL) { |
467 | CONTINUE_IF_NULL(oglc); |
468 | RESET_PREVIOUS_OP(); |
469 | OGLSD_Delete(env, oglsdo); |
470 | if (oglsdo->privOps != NULL) { |
471 | free(oglsdo->privOps); |
472 | } |
473 | } |
474 | } |
475 | break; |
476 | case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG: |
477 | { |
478 | jlong pConfigInfo = NEXT_LONG(b); |
479 | CONTINUE_IF_NULL(oglc); |
480 | RESET_PREVIOUS_OP(); |
481 | OGLGC_DestroyOGLGraphicsConfig(pConfigInfo); |
482 | |
483 | // the previous method will call glX/wglMakeCurrent(None), |
484 | // so we should nullify the current oglc and dstOps to avoid |
485 | // calling glFlush() (or similar) while no context is current |
486 | oglc = NULL; |
487 | dstOps = NULL; |
488 | } |
489 | break; |
490 | case sun_java2d_pipe_BufferedOpCodes_INVALIDATE_CONTEXT: |
491 | { |
492 | // flush just in case there are any pending operations in |
493 | // the hardware pipe |
494 | if (oglc != NULL) { |
495 | RESET_PREVIOUS_OP(); |
496 | j2d_glFlush(); |
497 | } |
498 | |
499 | // invalidate the references to the current context and |
500 | // destination surface that are maintained at the native level |
501 | oglc = NULL; |
502 | dstOps = NULL; |
503 | } |
504 | break; |
505 | case sun_java2d_pipe_BufferedOpCodes_SAVE_STATE: |
506 | { |
507 | j2d_glPushAttrib(GL_ALL_ATTRIB_BITS); |
508 | j2d_glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); |
509 | j2d_glMatrixMode(GL_MODELVIEW); |
510 | j2d_glPushMatrix(); |
511 | j2d_glMatrixMode(GL_PROJECTION); |
512 | j2d_glPushMatrix(); |
513 | j2d_glMatrixMode(GL_TEXTURE); |
514 | j2d_glPushMatrix(); |
515 | } |
516 | break; |
517 | |
518 | case sun_java2d_pipe_BufferedOpCodes_RESTORE_STATE: |
519 | { |
520 | j2d_glPopAttrib(); |
521 | j2d_glPopClientAttrib(); |
522 | j2d_glMatrixMode(GL_MODELVIEW); |
523 | j2d_glPopMatrix(); |
524 | j2d_glMatrixMode(GL_PROJECTION); |
525 | j2d_glPopMatrix(); |
526 | j2d_glMatrixMode(GL_TEXTURE); |
527 | j2d_glPopMatrix(); |
528 | } |
529 | break; |
530 | case sun_java2d_pipe_BufferedOpCodes_SYNC: |
531 | { |
532 | sync = JNI_TRUE; |
533 | } |
534 | break; |
535 | |
536 | // multibuffering ops |
537 | case sun_java2d_pipe_BufferedOpCodes_SWAP_BUFFERS: |
538 | { |
539 | jlong window = NEXT_LONG(b); |
540 | if (oglc != NULL) { |
541 | RESET_PREVIOUS_OP(); |
542 | } |
543 | OGLSD_SwapBuffers(env, window); |
544 | } |
545 | break; |
546 | |
547 | // special no-op (mainly used for achieving 8-byte alignment) |
548 | case sun_java2d_pipe_BufferedOpCodes_NOOP: |
549 | break; |
550 | |
551 | // paint-related ops |
552 | case sun_java2d_pipe_BufferedOpCodes_RESET_PAINT: |
553 | { |
554 | OGLPaints_ResetPaint(oglc); |
555 | } |
556 | break; |
557 | case sun_java2d_pipe_BufferedOpCodes_SET_COLOR: |
558 | { |
559 | jint pixel = NEXT_INT(b); |
560 | OGLPaints_SetColor(oglc, pixel); |
561 | } |
562 | break; |
563 | case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT: |
564 | { |
565 | jboolean useMask= NEXT_BOOLEAN(b); |
566 | jboolean cyclic = NEXT_BOOLEAN(b); |
567 | jdouble p0 = NEXT_DOUBLE(b); |
568 | jdouble p1 = NEXT_DOUBLE(b); |
569 | jdouble p3 = NEXT_DOUBLE(b); |
570 | jint pixel1 = NEXT_INT(b); |
571 | jint pixel2 = NEXT_INT(b); |
572 | OGLPaints_SetGradientPaint(oglc, useMask, cyclic, |
573 | p0, p1, p3, |
574 | pixel1, pixel2); |
575 | } |
576 | break; |
577 | case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT: |
578 | { |
579 | jboolean useMask = NEXT_BOOLEAN(b); |
580 | jboolean linear = NEXT_BOOLEAN(b); |
581 | jint cycleMethod = NEXT_INT(b); |
582 | jint numStops = NEXT_INT(b); |
583 | jfloat p0 = NEXT_FLOAT(b); |
584 | jfloat p1 = NEXT_FLOAT(b); |
585 | jfloat p3 = NEXT_FLOAT(b); |
586 | void *fractions, *pixels; |
587 | fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat)); |
588 | pixels = b; SKIP_BYTES(b, numStops * sizeof(jint)); |
589 | OGLPaints_SetLinearGradientPaint(oglc, dstOps, |
590 | useMask, linear, |
591 | cycleMethod, numStops, |
592 | p0, p1, p3, |
593 | fractions, pixels); |
594 | } |
595 | break; |
596 | case sun_java2d_pipe_BufferedOpCodes_SET_RADIAL_GRADIENT_PAINT: |
597 | { |
598 | jboolean useMask = NEXT_BOOLEAN(b); |
599 | jboolean linear = NEXT_BOOLEAN(b); |
600 | jint numStops = NEXT_INT(b); |
601 | jint cycleMethod = NEXT_INT(b); |
602 | jfloat m00 = NEXT_FLOAT(b); |
603 | jfloat m01 = NEXT_FLOAT(b); |
604 | jfloat m02 = NEXT_FLOAT(b); |
605 | jfloat m10 = NEXT_FLOAT(b); |
606 | jfloat m11 = NEXT_FLOAT(b); |
607 | jfloat m12 = NEXT_FLOAT(b); |
608 | jfloat focusX = NEXT_FLOAT(b); |
609 | void *fractions, *pixels; |
610 | fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat)); |
611 | pixels = b; SKIP_BYTES(b, numStops * sizeof(jint)); |
612 | OGLPaints_SetRadialGradientPaint(oglc, dstOps, |
613 | useMask, linear, |
614 | cycleMethod, numStops, |
615 | m00, m01, m02, |
616 | m10, m11, m12, |
617 | focusX, |
618 | fractions, pixels); |
619 | } |
620 | break; |
621 | case sun_java2d_pipe_BufferedOpCodes_SET_TEXTURE_PAINT: |
622 | { |
623 | jboolean useMask= NEXT_BOOLEAN(b); |
624 | jboolean filter = NEXT_BOOLEAN(b); |
625 | jlong pSrc = NEXT_LONG(b); |
626 | jdouble xp0 = NEXT_DOUBLE(b); |
627 | jdouble xp1 = NEXT_DOUBLE(b); |
628 | jdouble xp3 = NEXT_DOUBLE(b); |
629 | jdouble yp0 = NEXT_DOUBLE(b); |
630 | jdouble yp1 = NEXT_DOUBLE(b); |
631 | jdouble yp3 = NEXT_DOUBLE(b); |
632 | OGLPaints_SetTexturePaint(oglc, useMask, pSrc, filter, |
633 | xp0, xp1, xp3, |
634 | yp0, yp1, yp3); |
635 | } |
636 | break; |
637 | |
638 | // BufferedImageOp-related ops |
639 | case sun_java2d_pipe_BufferedOpCodes_ENABLE_CONVOLVE_OP: |
640 | { |
641 | jlong pSrc = NEXT_LONG(b); |
642 | jboolean edgeZero = NEXT_BOOLEAN(b); |
643 | jint kernelWidth = NEXT_INT(b); |
644 | jint kernelHeight = NEXT_INT(b); |
645 | OGLBufImgOps_EnableConvolveOp(oglc, pSrc, edgeZero, |
646 | kernelWidth, kernelHeight, b); |
647 | SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat)); |
648 | } |
649 | break; |
650 | case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP: |
651 | { |
652 | OGLBufImgOps_DisableConvolveOp(oglc); |
653 | } |
654 | break; |
655 | case sun_java2d_pipe_BufferedOpCodes_ENABLE_RESCALE_OP: |
656 | { |
657 | jlong pSrc = NEXT_LONG(b); |
658 | jboolean nonPremult = NEXT_BOOLEAN(b); |
659 | jint numFactors = 4; |
660 | unsigned char *scaleFactors = b; |
661 | unsigned char *offsets = (b + numFactors * sizeof(jfloat)); |
662 | OGLBufImgOps_EnableRescaleOp(oglc, pSrc, nonPremult, |
663 | scaleFactors, offsets); |
664 | SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2); |
665 | } |
666 | break; |
667 | case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP: |
668 | { |
669 | OGLBufImgOps_DisableRescaleOp(oglc); |
670 | } |
671 | break; |
672 | case sun_java2d_pipe_BufferedOpCodes_ENABLE_LOOKUP_OP: |
673 | { |
674 | jlong pSrc = NEXT_LONG(b); |
675 | jboolean nonPremult = NEXT_BOOLEAN(b); |
676 | jboolean shortData = NEXT_BOOLEAN(b); |
677 | jint numBands = NEXT_INT(b); |
678 | jint bandLength = NEXT_INT(b); |
679 | jint offset = NEXT_INT(b); |
680 | jint bytesPerElem = shortData ? sizeof(jshort):sizeof(jbyte); |
681 | void *tableValues = b; |
682 | OGLBufImgOps_EnableLookupOp(oglc, pSrc, nonPremult, shortData, |
683 | numBands, bandLength, offset, |
684 | tableValues); |
685 | SKIP_BYTES(b, numBands * bandLength * bytesPerElem); |
686 | } |
687 | break; |
688 | case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP: |
689 | { |
690 | OGLBufImgOps_DisableLookupOp(oglc); |
691 | } |
692 | break; |
693 | |
694 | default: |
695 | J2dRlsTraceLn1(J2D_TRACE_ERROR, |
696 | "OGLRenderQueue_flushBuffer: invalid opcode=%d" , opcode); |
697 | if (oglc != NULL) { |
698 | RESET_PREVIOUS_OP(); |
699 | } |
700 | return; |
701 | } |
702 | } |
703 | |
704 | if (oglc != NULL) { |
705 | RESET_PREVIOUS_OP(); |
706 | if (sync) { |
707 | j2d_glFinish(); |
708 | } else { |
709 | j2d_glFlush(); |
710 | } |
711 | OGLSD_Flush(env); |
712 | } |
713 | } |
714 | |
715 | /** |
716 | * Returns a pointer to the "current" context, as set by the last SET_SURFACES |
717 | * or SET_SCRATCH_SURFACE operation. |
718 | */ |
719 | OGLContext * |
720 | OGLRenderQueue_GetCurrentContext() |
721 | { |
722 | return oglc; |
723 | } |
724 | |
725 | /** |
726 | * Returns a pointer to the "current" destination surface, as set by the last |
727 | * SET_SURFACES operation. |
728 | */ |
729 | OGLSDOps * |
730 | OGLRenderQueue_GetCurrentDestination() |
731 | { |
732 | return dstOps; |
733 | } |
734 | |
735 | /** |
736 | * Used to track whether we are within a series of simple primitive operations |
737 | * or texturing operations. The op parameter determines the nature of the |
738 | * operation that is to follow. Valid values for this op parameter are: |
739 | * |
740 | * GL_QUADS |
741 | * GL_LINES |
742 | * GL_LINE_LOOP |
743 | * GL_LINE_STRIP |
744 | * (basically any of the valid parameters for glBegin()) |
745 | * |
746 | * GL_TEXTURE_2D |
747 | * GL_TEXTURE_RECTANGLE_ARB |
748 | * |
749 | * OGL_STATE_RESET |
750 | * OGL_STATE_CHANGE |
751 | * OGL_STATE_MASK_OP |
752 | * OGL_STATE_GLYPH_OP |
753 | * |
754 | * Note that the above constants are guaranteed to be unique values. The |
755 | * last few are defined to be negative values to differentiate them from |
756 | * the core GL* constants, which are defined to be non-negative. |
757 | * |
758 | * For simple primitives, this method allows us to batch similar primitives |
759 | * within the same glBegin()/glEnd() pair. For example, if we have 100 |
760 | * consecutive FILL_RECT operations, we only have to call glBegin(GL_QUADS) |
761 | * for the first op, and then subsequent operations will consist only of |
762 | * glVertex*() calls, which helps improve performance. The glEnd() call |
763 | * only needs to be issued before an operation that cannot happen within a |
764 | * glBegin()/glEnd() pair (e.g. updating the clip), or one that requires a |
765 | * different primitive mode (e.g. GL_LINES). |
766 | * |
767 | * For operations that involve texturing, this method helps us to avoid |
768 | * calling glEnable(GL_TEXTURE_2D) and glDisable(GL_TEXTURE_2D) around each |
769 | * operation. For example, if we have an alternating series of ISO_BLIT |
770 | * and MASK_BLIT operations (both of which involve texturing), we need |
771 | * only to call glEnable(GL_TEXTURE_2D) before the first ISO_BLIT operation. |
772 | * The glDisable(GL_TEXTURE_2D) call only needs to be issued before an |
773 | * operation that cannot (or should not) happen while texturing is enabled |
774 | * (e.g. a context change, or a simple primitive operation like GL_QUADS). |
775 | */ |
776 | void |
777 | OGLRenderQueue_CheckPreviousOp(jint op) |
778 | { |
779 | if (previousOp == op) { |
780 | // The op is the same as last time, so we can return immediately. |
781 | return; |
782 | } |
783 | |
784 | J2dTraceLn1(J2D_TRACE_VERBOSE, |
785 | "OGLRenderQueue_CheckPreviousOp: new op=%d" , op); |
786 | |
787 | switch (previousOp) { |
788 | case GL_TEXTURE_2D: |
789 | case GL_TEXTURE_RECTANGLE_ARB: |
790 | if (op == OGL_STATE_CHANGE) { |
791 | // Optimization: Certain state changes (those marked as |
792 | // OGL_STATE_CHANGE) are allowed while texturing is enabled. |
793 | // In this case, we can allow previousOp to remain as it is and |
794 | // then return early. |
795 | return; |
796 | } else { |
797 | // Otherwise, op must be a primitive operation, or a reset, so |
798 | // we will disable texturing. |
799 | j2d_glDisable(previousOp); |
800 | // This next step of binding to zero should not be strictly |
801 | // necessary, but on some older Nvidia boards (e.g. GeForce 2) |
802 | // problems will arise if GL_TEXTURE_2D and |
803 | // GL_TEXTURE_RECTANGLE_ARB are bound at the same time, so we |
804 | // will do this just to be safe. |
805 | j2d_glBindTexture(previousOp, 0); |
806 | } |
807 | break; |
808 | case OGL_STATE_MASK_OP: |
809 | OGLVertexCache_DisableMaskCache(oglc); |
810 | break; |
811 | case OGL_STATE_GLYPH_OP: |
812 | OGLTR_DisableGlyphVertexCache(oglc); |
813 | break; |
814 | case OGL_STATE_PGRAM_OP: |
815 | OGLRenderer_DisableAAParallelogramProgram(); |
816 | break; |
817 | case OGL_STATE_RESET: |
818 | case OGL_STATE_CHANGE: |
819 | // No-op |
820 | break; |
821 | default: |
822 | // In this case, op must be one of: |
823 | // - the start of a different primitive type (glBegin()) |
824 | // - a texturing operation |
825 | // - a state change (not allowed within glBegin()/glEnd() pairs) |
826 | // - a reset |
827 | // so we must first complete the previous primitive operation. |
828 | j2d_glEnd(); |
829 | break; |
830 | } |
831 | |
832 | switch (op) { |
833 | case GL_TEXTURE_2D: |
834 | case GL_TEXTURE_RECTANGLE_ARB: |
835 | // We are starting a texturing operation, so enable texturing. |
836 | j2d_glEnable(op); |
837 | break; |
838 | case OGL_STATE_MASK_OP: |
839 | OGLVertexCache_EnableMaskCache(oglc); |
840 | break; |
841 | case OGL_STATE_GLYPH_OP: |
842 | OGLTR_EnableGlyphVertexCache(oglc); |
843 | break; |
844 | case OGL_STATE_PGRAM_OP: |
845 | OGLRenderer_EnableAAParallelogramProgram(); |
846 | break; |
847 | case OGL_STATE_RESET: |
848 | case OGL_STATE_CHANGE: |
849 | // No-op |
850 | break; |
851 | default: |
852 | // We are starting a primitive operation, so call glBegin() with |
853 | // the given primitive type. |
854 | j2d_glBegin(op); |
855 | break; |
856 | } |
857 | |
858 | previousOp = op; |
859 | } |
860 | |
861 | #endif /* !HEADLESS */ |
862 | |