com.sun.webkit.graphics.WCRenderQueue Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.webkit.graphics;
import java.lang.annotation.Native;
import com.sun.javafx.logging.PlatformLogger;
import com.sun.javafx.logging.PlatformLogger.Level;
import com.sun.webkit.Invoker;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class WCRenderQueue extends Ref {
private final static AtomicInteger idCountObj = new AtomicInteger(0);
private final static PlatformLogger log =
PlatformLogger.getLogger(WCRenderQueue.class.getName());
@Native public final static int MAX_QUEUE_SIZE = 0x80000;
private final LinkedList buffers = new LinkedList<>();
private BufferData currentBuffer = new BufferData();
private final WCRectangle clip;
private int size = 0;
private final boolean opaque;
// Associated graphics context (currently used to draw to a buffered image).
protected final WCGraphicsContext gc;
protected WCRenderQueue(WCGraphicsContext gc) {
this.clip = null;
this.opaque = false;
this.gc = gc;
}
protected WCRenderQueue(WCRectangle clip, boolean opaque) {
this.clip = clip;
this.opaque = opaque;
this.gc = null;
}
public synchronized int getSize() {
return size;
}
public synchronized void addBuffer(ByteBuffer buffer) {
if (log.isLoggable(Level.FINE) && buffers.isEmpty()) {
log.fine("'{'WCRenderQueue{0}[{1}]",
new Object[]{hashCode(), idCountObj.incrementAndGet()});
}
currentBuffer.setBuffer(buffer);
buffers.addLast(currentBuffer);
currentBuffer = new BufferData();
size += buffer.capacity();
if (size > MAX_QUEUE_SIZE && gc!=null) {
// It is isolated queue over the canvas image [image-gc!=null].
// We need to flush the changes periodically
// by the same reason as in [WebPage.addLastRQ].
flush();
}
}
public synchronized boolean isEmpty() {
return buffers.isEmpty();
}
public synchronized void decode(WCGraphicsContext gc) {
if (gc == null || !gc.isValid()) {
log.fine("WCRenderQueue::decode : GC is " + (gc == null ? "null" : " invalid"));
return;
}
for (BufferData bdata : buffers) {
try {
GraphicsDecoder.decode(
WCGraphicsManager.getGraphicsManager(), gc, bdata);
} catch (RuntimeException e) {
e.printStackTrace(System.err);
}
}
dispose();
}
public synchronized void decode() {
if (gc == null || !gc.isValid()) {
log.fine("WCRenderQueue::decode : GC is " + (gc == null ? "null" : " invalid"));
return;
}
decode(gc);
gc.flush();
}
public synchronized void decode(int fontSmoothingType) {
if (gc == null || !gc.isValid()) {
log.fine("WCRenderQueue::decode : GC is " + (gc == null ? "null" : " invalid"));
return;
}
gc.setFontSmoothingType(fontSmoothingType);
decode();
}
protected abstract void flush();
private void fwkFlush() {
flush();
}
private void fwkAddBuffer(ByteBuffer buffer) {
addBuffer(buffer);
}
public WCRectangle getClip() {
return clip;
}
public synchronized void dispose() {
int n = buffers.size();
if (n > 0) {
int i = 0;
final Object[] arr = new Object[n];
for (BufferData bdata: buffers) {
arr[i++] = bdata.getBuffer();
}
buffers.clear();
Invoker.getInvoker().invokeOnEventThread(() -> {
twkRelease(arr);
});
size = 0;
if (log.isLoggable(Level.FINE)) {
log.fine("'}'WCRenderQueue{0}[{1}]",
new Object[]{hashCode(), idCountObj.decrementAndGet()});
}
}
}
protected abstract void disposeGraphics();
private void fwkDisposeGraphics() {
disposeGraphics();
}
private native void twkRelease(Object[] bufs);
/*is called from native*/
private int refString(String str) {
return currentBuffer.addString(str);
}
/*is called from native*/
private int refIntArr(int[] arr) {
return currentBuffer.addIntArray(arr);
}
/*is called from native*/
private int refFloatArr(float[] arr) {
return currentBuffer.addFloatArray(arr);
}
public boolean isOpaque() {
return opaque;
}
@Override public synchronized String toString() {
return "WCRenderQueue{"
+ "clip=" + clip + ", "
+ "size=" + size + ", "
+ "opaque=" + opaque
+ "}";
}
}
final class BufferData {
/* For passing data that does not fit into the queue */
private final AtomicInteger idCount = new AtomicInteger(0);
private final HashMap strMap =
new HashMap<>();
private final HashMap intArrMap =
new HashMap<>();
private final HashMap floatArrMap =
new HashMap<>();
private ByteBuffer buffer;
private int createID() {
return idCount.incrementAndGet();
}
int addIntArray(int[] a) {
int id = createID();
intArrMap.put(id, a);
return id;
}
int[] getIntArray(int id) {
return intArrMap.get(id);
}
int addFloatArray(float[] a) {
int id = createID();
floatArrMap.put(id, a);
return id;
}
float[] getFloatArray(int id) {
return floatArrMap.get(id);
}
int addString(String s) {
int id = createID();
strMap.put(id, s);
return id;
}
String getString(int id) {
return strMap.get(id);
}
ByteBuffer getBuffer() {
return buffer;
}
void setBuffer(ByteBuffer buffer) {
this.buffer = buffer;
}
}