1 /* 2 * Copyright (c) 2009, 2013, 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 package com.sun.prism.impl; 27 28 import com.sun.javafx.geom.transform.AffineBase; 29 import com.sun.prism.paint.Color; 30 import java.util.Arrays; 31 32 public class VertexBuffer { 33 34 protected static final int VERTS_PER_QUAD = 4; 35 36 protected static final int FLOATS_PER_TC = 2; 37 protected static final int FLOATS_PER_VC = 3; 38 protected static final int FLOATS_PER_VERT = FLOATS_PER_VC + (2 * FLOATS_PER_TC); 39 40 protected static final int BYTES_PER_VERT = 4; 41 42 protected static final int VCOFF = 0; 43 protected static final int TC1OFF = VCOFF + FLOATS_PER_VC; 44 protected static final int TC2OFF = TC1OFF + FLOATS_PER_TC; 45 46 protected int capacity, index; 47 48 protected byte r, g, b, a; 49 50 protected byte colorArray[]; 51 protected float coordArray[]; 52 53 public VertexBuffer(int maxQuads) { 54 capacity = maxQuads * VERTS_PER_QUAD; 55 index = 0; 56 57 colorArray = new byte [capacity * BYTES_PER_VERT]; 58 coordArray = new float[capacity * FLOATS_PER_VERT]; 59 } 60 61 protected void drawQuads(int numVertices) { 62 throw new Error ("flush not implemented for lightweight"); 63 } 64 65 // it had better be the case if this method be moved to Graphics 66 // so that we can delete D3DVertexBuffer and ES2(N)VertexBuffer 67 protected void drawTriangles(int numTriangles, float fData[], byte cData[]) { 68 throw new Error ("flush not implemented for lightweight"); 69 } 70 71 public final void setPerVertexColor(Color c, float extraAlpha) { 72 float ca = c.getAlpha() * extraAlpha; 73 r = (byte)(c.getRed() * ca * 0xff); 74 g = (byte)(c.getGreen() * ca * 0xff); 75 b = (byte)(c.getBlue() * ca * 0xff); 76 a = (byte)( ca * 0xff); 77 } 78 79 public final void setPerVertexColor(float extraAlpha) { 80 r = g = b = a = (byte)(extraAlpha * 0xff); 81 } 82 83 public final void updateVertexColors(int numVerts) { 84 for (int i=0; i!=numVerts; ++i) { 85 putColor(i); 86 } 87 } 88 89 private void putColor(int idx) { 90 int i = idx * BYTES_PER_VERT; 91 colorArray[i+0] = r; 92 colorArray[i+1] = g; 93 colorArray[i+2] = b; 94 colorArray[i+3] = a; 95 } 96 97 /** 98 * Flushes (renders) all pending vertices (triangles) in the buffer to the 99 * destination render target. This operation only applies to heavyweight 100 * buffers; calling flush() on a lightweight buffer will result in an 101 * exception. 102 */ 103 public final void flush() { 104 if (index > 0) { 105 drawQuads(index); 106 index = 0; 107 } 108 } 109 110 public final void rewind() { 111 index = 0; 112 } 113 114 private void grow() { 115 capacity *= 2; 116 colorArray = Arrays.copyOf(colorArray, capacity * BYTES_PER_VERT); 117 coordArray = Arrays.copyOf(coordArray, capacity * FLOATS_PER_VERT); 118 } 119 120 public final void addVert(float x, float y) { 121 // unlike the other (private) addVert() variants, this checks capacity 122 if (index == capacity) { 123 grow(); 124 } 125 126 int i = FLOATS_PER_VERT * index; 127 coordArray[i+0] = x; 128 coordArray[i+1] = y; 129 coordArray[i+2] = 0f; 130 putColor(index); 131 index++; 132 } 133 134 public final void addVert(float x, float y, float tx, float ty) { 135 // unlike the (private) addVert() variants, this checks capacity 136 if (index == capacity) { 137 grow(); 138 } 139 140 int i = FLOATS_PER_VERT * index; 141 coordArray[i+0] = x; 142 coordArray[i+1] = y; 143 coordArray[i+2] = 0f; 144 coordArray[i+3] = tx; 145 coordArray[i+4] = ty; 146 putColor(index); 147 index++; 148 } 149 150 public final void addVert(float x, float y, float t0x, float t0y, float t1x, float t1y) { 151 // unlike the (private) addVert() variants, this checks capacity 152 if (index == capacity) { 153 grow(); 154 } 155 156 int i = FLOATS_PER_VERT * index; 157 coordArray[i+0] = x; 158 coordArray[i+1] = y; 159 coordArray[i+2] = 0f; 160 coordArray[i+3] = t0x; 161 coordArray[i+4] = t0y; 162 coordArray[i+5] = t1x; 163 coordArray[i+6] = t1y; 164 putColor(index); 165 index++; 166 } 167 168 private void addVertNoCheck(float x, float y) { 169 // note: assumes caller has already checked capacity 170 int i = FLOATS_PER_VERT * index; 171 coordArray[i+0] = x; 172 coordArray[i+1] = y; 173 coordArray[i+2] = 0f; 174 putColor(index); 175 index++; 176 } 177 178 private void addVertNoCheck(float x, float y, float tx, float ty) { 179 // note: assumes caller has already checked capacity 180 int i = FLOATS_PER_VERT * index; 181 coordArray[i+0] = x; 182 coordArray[i+1] = y; 183 coordArray[i+2] = 0f; 184 coordArray[i+3] = tx; 185 coordArray[i+4] = ty; 186 putColor(index); 187 index++; 188 } 189 190 private void addVertNoCheck(float x, float y, float t0x, float t0y, float t1x, float t1y) { 191 // note: assumes caller has already checked capacity 192 int i = FLOATS_PER_VERT * index; 193 coordArray[i+0] = x; 194 coordArray[i+1] = y; 195 coordArray[i+2] = 0f; 196 coordArray[i+3] = t0x; 197 coordArray[i+4] = t0y; 198 coordArray[i+5] = t1x; 199 coordArray[i+6] = t1y; 200 putColor(index); 201 index++; 202 } 203 204 // render a trianglelist 205 public final void addVerts(VertexBuffer vb, int numVerts) { 206 flush(); 207 drawTriangles(numVerts/3, vb.coordArray, vb.colorArray); 208 } 209 210 private void ensureCapacityForQuad() { 211 if (index + VERTS_PER_QUAD > capacity) { 212 drawQuads(index); 213 index = 0; 214 } 215 } 216 217 public final void addQuad(float dx1, float dy1, float dx2, float dy2) { 218 ensureCapacityForQuad(); 219 220 addVertNoCheck(dx1, dy1); 221 addVertNoCheck(dx1, dy2); 222 addVertNoCheck(dx2, dy1); 223 addVertNoCheck(dx2, dy2); 224 } 225 226 public final void addQuad( 227 float dx1, float dy1, float dx2, float dy2, 228 float t1x1, float t1y1, float t1x2, float t1y2, 229 float t2x1, float t2y1, float t2x2, float t2y2) 230 { 231 ensureCapacityForQuad(); 232 233 addVertNoCheck(dx1, dy1, t1x1, t1y1, t2x1, t2y1); 234 addVertNoCheck(dx1, dy2, t1x1, t1y2, t2x1, t2y2); 235 addVertNoCheck(dx2, dy1, t1x2, t1y1, t2x2, t2y1); 236 addVertNoCheck(dx2, dy2, t1x2, t1y2, t2x2, t2y2); 237 } 238 239 public final void addMappedQuad( 240 float dx1, float dy1, float dx2, float dy2, 241 float tx11, float ty11, float tx21, float ty21, 242 float tx12, float ty12, float tx22, float ty22) 243 { 244 ensureCapacityForQuad(); 245 246 addVertNoCheck(dx1, dy1, tx11, ty11); 247 addVertNoCheck(dx1, dy2, tx12, ty12); 248 addVertNoCheck(dx2, dy1, tx21, ty21); 249 addVertNoCheck(dx2, dy2, tx22, ty22); 250 } 251 252 public final void addMappedQuad( 253 float dx1, float dy1, float dx2, float dy2, 254 float ux11, float uy11, float ux21, float uy21, 255 float ux12, float uy12, float ux22, float uy22, 256 float vx11, float vy11, float vx21, float vy21, 257 float vx12, float vy12, float vx22, float vy22) 258 { 259 ensureCapacityForQuad(); 260 261 addVertNoCheck(dx1, dy1, ux11, uy11, vx11, vy11); 262 addVertNoCheck(dx1, dy2, ux12, uy12, vx12, vy12); 263 addVertNoCheck(dx2, dy1, ux21, uy21, vx21, vy21); 264 addVertNoCheck(dx2, dy2, ux22, uy22, vx22, vy22); 265 } 266 267 public final void addQuad( 268 float dx1, float dy1, float dx2, float dy2, 269 float tx1, float ty1, float tx2, float ty2, 270 AffineBase tx) 271 { 272 addQuad(dx1, dy1, dx2, dy2, tx1, ty1, tx2, ty2); 273 274 if (tx != null) { 275 int i = FLOATS_PER_VERT * index - FLOATS_PER_VERT; 276 tx.transform(coordArray, i+VCOFF, coordArray, i+TC2OFF, 1); 277 i -= FLOATS_PER_VERT; 278 tx.transform(coordArray, i+VCOFF, coordArray, i+TC2OFF, 1); 279 i -= FLOATS_PER_VERT; 280 tx.transform(coordArray, i+VCOFF, coordArray, i+TC2OFF, 1); 281 i -= FLOATS_PER_VERT; 282 tx.transform(coordArray, i+VCOFF, coordArray, i+TC2OFF, 1); 283 } 284 } 285 286 public final void addSuperQuad( 287 float dx1, float dy1, float dx2, float dy2, 288 float tx1, float ty1, float tx2, float ty2, 289 boolean isText) 290 { 291 // ensureCapacityForQuad(); 292 int idx = index; 293 if (idx + VERTS_PER_QUAD > capacity) { 294 // grow(); 295 drawQuads(idx); 296 idx = index = 0; 297 } 298 299 int i = FLOATS_PER_VERT * idx; 300 float farr[] = coordArray; 301 302 float text = isText ? 1 : 0; 303 float image = isText ? 0 : 1; 304 305 // addVertNoCheck(dx1, dy1, tx1, ty1); 306 farr[ i] = dx1; farr[++i] = dy1; farr[++i] = 0; 307 farr[++i] = tx1; farr[++i] = ty1; 308 farr[++i] = image; farr[++i] = text; i++; 309 // addVertNoCheck(dx1, dy2, tx1, ty2); 310 farr[ i] = dx1; farr[++i] = dy2; farr[++i] = 0; 311 farr[++i] = tx1; farr[++i] = ty2; 312 farr[++i] = image; farr[++i] = text; i++; 313 // addVertNoCheck(dx2, dy1, tx2, ty1); 314 farr[ i] = dx2; farr[++i] = dy1; farr[++i] = 0; 315 farr[++i] = tx2; farr[++i] = ty1; 316 farr[++i] = image; farr[++i] = text; i++; 317 // addVertNoCheck(dx2, dy2, tx2, ty2); 318 farr[ i] = dx2; farr[++i] = dy2; farr[++i] = 0; 319 farr[++i] = tx2; farr[++i] = ty2; 320 farr[++i] = image; farr[++i] = text; i++; 321 322 byte barr[] = colorArray; 323 byte r = this.r, g = this.g, b = this.b, a = this.a; 324 int j = BYTES_PER_VERT * idx; 325 barr[ j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 326 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 327 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 328 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 329 330 index = idx + VERTS_PER_QUAD; 331 } 332 333 public final void addQuad( 334 float dx1, float dy1, float dx2, float dy2, 335 float tx1, float ty1, float tx2, float ty2) 336 { 337 // ensureCapacityForQuad(); 338 int idx = index; 339 if (idx + VERTS_PER_QUAD > capacity) { 340 drawQuads(idx); 341 idx = index = 0; 342 } 343 344 int i = FLOATS_PER_VERT * idx; 345 float farr[] = coordArray; 346 347 // addVertNoCheck(dx1, dy1, tx1, ty1); 348 farr[ i] = dx1; farr[++i] = dy1; farr[++i] = 0; 349 farr[++i] = tx1; farr[++i] = ty1; 350 i += 3; 351 // addVertNoCheck(dx1, dy2, tx1, ty2); 352 farr[ i] = dx1; farr[++i] = dy2; farr[++i] = 0; 353 farr[++i] = tx1; farr[++i] = ty2; 354 i += 3; 355 // addVertNoCheck(dx2, dy1, tx2, ty1); 356 farr[ i] = dx2; farr[++i] = dy1; farr[++i] = 0; 357 farr[++i] = tx2; farr[++i] = ty1; 358 i += 3; 359 // addVertNoCheck(dx2, dy2, tx2, ty2); 360 farr[ i] = dx2; farr[++i] = dy2; farr[++i] = 0; 361 farr[++i] = tx2; farr[++i] = ty2; 362 363 byte barr[] = colorArray; 364 byte r = this.r, g = this.g, b = this.b, a = this.a; 365 int j = BYTES_PER_VERT * idx; 366 barr[ j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 367 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 368 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 369 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 370 371 index = idx + VERTS_PER_QUAD; 372 } 373 374 public final void addQuadVO(float topopacity, float botopacity, 375 float dx1, float dy1, float dx2, float dy2, 376 float tx1, float ty1, float tx2, float ty2) 377 { 378 int idx = index; 379 if (idx + VERTS_PER_QUAD > capacity) { 380 drawQuads(idx); 381 idx = index = 0; 382 } 383 384 int i = FLOATS_PER_VERT * idx; 385 float farr[] = coordArray; 386 387 // addVertNoCheck(dx1, dy1, tx1, ty1, topopacity); 388 farr[ i] = dx1; farr[++i] = dy1; farr[++i] = 0; 389 farr[++i] = tx1; farr[++i] = ty1; 390 i += 3; 391 392 // addVertNoCheck(dx1, dy2, tx1, ty2, botopacity); 393 farr[ i] = dx1; farr[++i] = dy2; farr[++i] = 0; 394 farr[++i] = tx1; farr[++i] = ty2; 395 i += 3; 396 397 // addVertNoCheck(dx2, dy1, tx2, ty1, topopacity); 398 farr[ i] = dx2; farr[++i] = dy1; farr[++i] = 0; 399 farr[++i] = tx2; farr[++i] = ty1; 400 i += 3; 401 402 // addVertNoCheck(dx2, dy2, tx2, ty2, botopacity); 403 farr[ i] = dx2; farr[++i] = dy2; farr[++i] = 0; 404 farr[++i] = tx2; farr[++i] = ty2; 405 406 byte barr[] = colorArray; 407 int j = BYTES_PER_VERT * idx; 408 409 byte to = (byte)(topopacity * 0xff); 410 byte bo = (byte)(botopacity * 0xff); 411 412 barr[ j] = to; barr[++j] = to; barr[++j] = to; barr[++j] = to; 413 barr[++j] = bo; barr[++j] = bo; barr[++j] = bo; barr[++j] = bo; 414 barr[++j] = to; barr[++j] = to; barr[++j] = to; barr[++j] = to; 415 barr[++j] = bo; barr[++j] = bo; barr[++j] = bo; barr[++j] = bo; 416 417 index = idx + VERTS_PER_QUAD; 418 } 419 420 public final void addMappedPgram( 421 float dx11, float dy11, float dx21, float dy21, 422 float dx12, float dy12, float dx22, float dy22, 423 float ux11, float uy11, float ux21, float uy21, 424 float ux12, float uy12, float ux22, float uy22, 425 float vx11, float vy11, float vx22, float vy22, 426 AffineBase tx) 427 { 428 addMappedPgram(dx11, dy11, dx21, dy21, dx12, dy12, dx22, dy22, 429 ux11, uy11, ux21, uy21, ux12, uy12, ux22, uy22, 430 vx11, vy11, vx22, vy11, vx11, vy22, vx22, vy22); 431 432 int i = FLOATS_PER_VERT * index - FLOATS_PER_VERT; 433 tx.transform(coordArray, i+TC2OFF, coordArray, i+TC2OFF, 1); 434 i -= FLOATS_PER_VERT; 435 tx.transform(coordArray, i+TC2OFF, coordArray, i+TC2OFF, 1); 436 i -= FLOATS_PER_VERT; 437 tx.transform(coordArray, i+TC2OFF, coordArray, i+TC2OFF, 1); 438 i -= FLOATS_PER_VERT; 439 tx.transform(coordArray, i+TC2OFF, coordArray, i+TC2OFF, 1); 440 } 441 442 public final void addMappedPgram( 443 float dx11, float dy11, float dx21, float dy21, 444 float dx12, float dy12, float dx22, float dy22, 445 float ux11, float uy11, float ux21, float uy21, 446 float ux12, float uy12, float ux22, float uy22, 447 float vx, float vy) 448 { 449 int idx = index; 450 if (idx + VERTS_PER_QUAD > capacity) { 451 drawQuads(idx); 452 idx = index = 0; 453 } 454 455 int i = FLOATS_PER_VERT * idx; 456 float farr[] = coordArray; 457 458 //addVertNoCheck(dx11, dy11, ux11, uy11, vx, vy); 459 farr[i] = dx11; farr[++i] = dy11; farr[++i] = 0; 460 farr[++i] = ux11; farr[++i] = uy11; 461 farr[++i] = vx; farr[++i] = vy; 462 463 //addVertNoCheck(dx12, dy12, ux12, uy12, vx, vy); 464 farr[++i] = dx12; farr[++i] = dy12; farr[++i] = 0; 465 farr[++i] = ux12; farr[++i] = uy12; 466 farr[++i] = vx; farr[++i] = vy; 467 468 //addVertNoCheck(dx21, dy21, ux21, uy21, vx, vy); 469 farr[++i] = dx21; farr[++i] = dy21; farr[++i] = 0; 470 farr[++i] = ux21; farr[++i] = uy21; 471 farr[++i] = vx; farr[++i] = vy; 472 473 //addVertNoCheck(dx22, dy22, ux22, uy22, vx, vy); 474 farr[++i] = dx22; farr[++i] = dy22; farr[++i] = 0; 475 farr[++i] = ux22; farr[++i] = uy22; 476 farr[++i] = vx; farr[++i] = vy; 477 478 byte barr[] = colorArray; 479 byte r = this.r, g = this.g, b = this.b, a = this.a; 480 int j = BYTES_PER_VERT * idx; 481 barr[ j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 482 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 483 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 484 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 485 486 index = idx + VERTS_PER_QUAD; 487 } 488 489 public final void addMappedPgram( 490 float dx11, float dy11, float dx21, float dy21, 491 float dx12, float dy12, float dx22, float dy22, 492 float ux11, float uy11, float ux21, float uy21, 493 float ux12, float uy12, float ux22, float uy22, 494 float vx11, float vy11, float vx21, float vy21, 495 float vx12, float vy12, float vx22, float vy22) 496 { 497 int idx = index; 498 if (idx + VERTS_PER_QUAD > capacity) { 499 drawQuads(idx); 500 idx = index = 0; 501 } 502 503 int i = FLOATS_PER_VERT * idx; 504 float farr[] = coordArray; 505 506 //addVertNoCheck(dx11, dy11, ux11, uy11, vx, vy); 507 farr[i] = dx11; farr[++i] = dy11; farr[++i] = 0; 508 farr[++i] = ux11; farr[++i] = uy11; 509 farr[++i] = vx11; farr[++i] = vy11; 510 511 //addVertNoCheck(dx12, dy12, ux12, uy12, vx, vy); 512 farr[++i] = dx12; farr[++i] = dy12; farr[++i] = 0; 513 farr[++i] = ux12; farr[++i] = uy12; 514 farr[++i] = vx12; farr[++i] = vy12; 515 516 //addVertNoCheck(dx21, dy21, ux21, uy21, vx, vy); 517 farr[++i] = dx21; farr[++i] = dy21; farr[++i] = 0; 518 farr[++i] = ux21; farr[++i] = uy21; 519 farr[++i] = vx21; farr[++i] = vy21; 520 521 //addVertNoCheck(dx22, dy22, ux22, uy22, vx, vy); 522 farr[++i] = dx22; farr[++i] = dy22; farr[++i] = 0; 523 farr[++i] = ux22; farr[++i] = uy22; 524 farr[++i] = vx22; farr[++i] = vy22; 525 526 byte barr[] = colorArray; 527 byte r = this.r, g = this.g, b = this.b, a = this.a; 528 int j = BYTES_PER_VERT * idx; 529 barr[ j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 530 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 531 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 532 barr[++j] = r; barr[++j] = g; barr[++j] = b; barr[++j] = a; 533 534 index = idx + VERTS_PER_QUAD; 535 } 536 }