All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.prism.impl.QueuedPixelSource Maven / Gradle / Ivy

There is a newer version: 24-ea+15
Show newest version
/*
 * Copyright (c) 2014, 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.prism.impl;

import com.sun.glass.ui.Application;
import com.sun.glass.ui.Pixels;
import com.sun.prism.PixelSource;
import java.lang.ref.WeakReference;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * Base concrete implementation of the {@code PixelSource} interface which
 * manages {@link Pixels} objects in the state of being consumed (uploaded
 * to the screen usually), in flight in the queue of upload requests, and
 * idle waiting to be reused for temporary storage for future uploads.
 * All {@code Pixels} objects currently saved for reuse will all be the
 * same dimensions and scale which are tracked by calling the
 * {@link #validate(int, int, float) validate()} method.
 * 

* At most we will need 3 sets of pixels: * One may be "in use", a hard reference stored in beingConsumed * Another may be "in the queue", hard ref stored in enqueued * A third may be needed to prepare new pixels while those two are in * transit. * If the third is filled with pixels and enqueued while the previously * mentioned two are still in their stages of use, then it will replace * the second object as the "enqueued" reference and the previously * enqueued object will then become itself the "third unused" reference. * If everything happens in lock step we will often have only one * set of pixels. If the consumer/displayer gets slightly or occasionally * behind we might end up with two sets of pixels in play. Only when things * get really bad with multiple deliveries enqueued during the processing * of a single earlier delivery will we end up with three sets of * {@code Pixels} objects in play. */ public class QueuedPixelSource implements PixelSource { private volatile Pixels beingConsumed; private volatile Pixels enqueued; private final List> saved = new ArrayList<>(3); private final boolean useDirectBuffers; public QueuedPixelSource(boolean useDirectBuffers) { this.useDirectBuffers = useDirectBuffers; } @Override public synchronized Pixels getLatestPixels() { if (beingConsumed != null) { throw new IllegalStateException("already consuming pixels: "+beingConsumed); } if (enqueued != null) { beingConsumed = enqueued; enqueued = null; } return beingConsumed; } @Override public synchronized void doneWithPixels(Pixels used) { if (beingConsumed != used) { throw new IllegalStateException("wrong pixels buffer: "+used+" != "+beingConsumed); } beingConsumed = null; } @Override public synchronized void skipLatestPixels() { if (beingConsumed != null) { throw new IllegalStateException("cannot skip while processing: "+beingConsumed); } enqueued = null; } private boolean usesSameBuffer(Pixels p1, Pixels p2) { if (p1 == p2) return true; if (p1 == null || p2 == null) return false; return (p1.getBuffer() == p2.getBuffer()); } /** * Return an unused Pixels with the indicated dimensions and scale. * The returned object may either be saved from a previous use, but * currently not being consumed or in the queue. * Or it may be an object that reuses a buffer from a previously * used (but not active) {@code Pixels} object. * Or it may be a brand new object. * * @param w the width of the desired Pixels object * @param h the height of the desired Pixels object * @param scalex the horizontal scale of the desired Pixels object * @param scaley the vertical scale of the desired Pixels object * @return an unused {@code Pixels} object */ public synchronized Pixels getUnusedPixels(int w, int h, float scalex, float scaley) { int i = 0; IntBuffer reuseBuffer = null; while (i < saved.size()) { WeakReference ref = saved.get(i); Pixels p = ref.get(); if (p == null) { saved.remove(i); continue; } if (usesSameBuffer(p, beingConsumed) || usesSameBuffer(p, enqueued)) { i++; continue; } if (p.getWidthUnsafe() == w && p.getHeightUnsafe() == h && p.getScaleXUnsafe() == scalex && p.getScaleYUnsafe() == scaley) { return p; } // Whether or not we reuse its buffer, this Pixels object is going away. saved.remove(i); reuseBuffer = (IntBuffer) p.getPixels(); if (reuseBuffer.capacity() >= w * h) { break; } reuseBuffer = null; // Loop around and see if there are any other buffers to reuse, // or get rid of all of the buffers that are too small before // we proceed on to the allocation code. } if (reuseBuffer == null) { int bufsize = w * h; if (useDirectBuffers) { reuseBuffer = BufferUtil.newIntBuffer(bufsize); } else { reuseBuffer = IntBuffer.allocate(bufsize); } } Pixels p = Application.GetApplication().createPixels(w, h, reuseBuffer, scalex, scaley); saved.add(new WeakReference<>(p)); return p; } /** * Place the indicated {@code Pixels} object into the enqueued state, * replacing any other objects that are currently enqueued but not yet * being used by the consumer. * * @param pixels the {@code Pixels} object to be enqueued */ public synchronized void enqueuePixels(Pixels pixels) { enqueued = pixels; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy