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