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 */
51jint previousOp;
52
53/**
54 * References to the "current" context and destination surface.
55 */
56static OGLContext *oglc = NULL;
57static OGLSDOps *dstOps = NULL;
58
59/**
60 * The following methods are implemented in the windowing system (i.e. GLX
61 * and WGL) source files.
62 */
63extern OGLContext *OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo);
64extern void OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo);
65extern void OGLSD_SwapBuffers(JNIEnv *env, jlong window);
66extern void OGLSD_Flush(JNIEnv *env);
67
68JNIEXPORT void JNICALL
69Java_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 */
719OGLContext *
720OGLRenderQueue_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 */
729OGLSDOps *
730OGLRenderQueue_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 */
776void
777OGLRenderQueue_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