blob: 2c9f1d97543ae12592595d65cde668f332f8f084 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.SystemClock;
import android.os.Trace;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
import java.io.PrintWriter;
/**
* Hardware renderer that proxies the rendering to a render thread. Most calls
* are currently synchronous.
* TODO: Make draw() async.
* TODO: Figure out how to share the DisplayList between two threads (global lock?)
*
* The UI thread can block on the RenderThread, but RenderThread must never
* block on the UI thread.
*
* ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
* and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
* by the lifecycle of the RenderProxy.
*
* Note that although currently the EGL context & surfaces are created & managed
* by the render thread, the goal is to move that into a shared structure that can
* be managed by both threads. EGLSurface creation & deletion should ideally be
* done on the UI thread and not the RenderThread to avoid stalling the
* RenderThread with surface buffer allocation.
*
* @hide
*/
public class ThreadedRenderer extends HardwareRenderer {
private static final String LOGTAG = "ThreadedRenderer";
private static final Rect NULL_RECT = new Rect(-1, -1, -1, -1);
private int mWidth, mHeight;
private long mNativeProxy;
ThreadedRenderer(boolean translucent) {
mNativeProxy = nCreateProxy(translucent);
setEnabled(mNativeProxy != 0);
}
@Override
void destroy(boolean full) {
nDestroyCanvas(mNativeProxy);
}
@Override
boolean initialize(Surface surface) throws OutOfResourcesException {
return nInitialize(mNativeProxy, surface);
}
@Override
void updateSurface(Surface surface) throws OutOfResourcesException {
nUpdateSurface(mNativeProxy, surface);
}
@Override
void destroyLayers(View view) {
throw new NoSuchMethodError();
}
@Override
void destroyHardwareResources(View view) {
// TODO: canvas.clearLayerUpdates()
destroyResources(view);
// TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
}
private static void destroyResources(View view) {
view.destroyHardwareResources();
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
int count = group.getChildCount();
for (int i = 0; i < count; i++) {
destroyResources(group.getChildAt(i));
}
}
}
@Override
void invalidate(Surface surface) {
updateSurface(surface);
}
@Override
boolean validate() {
// TODO Remove users of this API
return false;
}
@Override
boolean safelyRun(Runnable action) {
// TODO:
return false;
}
@Override
void setup(int width, int height) {
mWidth = width;
mHeight = height;
nSetup(mNativeProxy, width, height);
}
@Override
int getWidth() {
return mWidth;
}
@Override
int getHeight() {
return mHeight;
}
@Override
void dumpGfxInfo(PrintWriter pw) {
// TODO Auto-generated method stub
}
@Override
long getFrameCount() {
// TODO Auto-generated method stub
return 0;
}
@Override
boolean loadSystemProperties() {
return false;
}
@Override
void pushLayerUpdate(HardwareLayer layer) {
throw new NoSuchMethodError();
}
@Override
void cancelLayerUpdate(HardwareLayer layer) {
throw new NoSuchMethodError();
}
@Override
void flushLayerUpdates() {
throw new NoSuchMethodError();
}
/**
* TODO: Remove
* Temporary hack to allow RenderThreadTest prototype app to trigger
* replaying a DisplayList after modifying the displaylist properties
*
* @hide */
public void repeatLastDraw() {
}
@Override
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
attachInfo.mIgnoreDirtyState = true;
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
view.mPrivateFlags |= View.PFLAG_DRAWN;
view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
== View.PFLAG_INVALIDATED;
view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
DisplayList displayList = view.getDisplayList();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
view.mRecreateDisplayList = false;
if (dirty == null) {
dirty = NULL_RECT;
}
nDrawDisplayList(mNativeProxy, displayList.getNativeDisplayList(),
dirty.left, dirty.top, dirty.right, dirty.bottom);
}
@Override
HardwareLayer createHardwareLayer(boolean isOpaque) {
throw new NoSuchMethodError();
}
@Override
HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
throw new NoSuchMethodError();
}
@Override
SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
throw new NoSuchMethodError();
}
@Override
void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
throw new NoSuchMethodError();
}
@Override
void detachFunctor(long functor) {
nDetachFunctor(mNativeProxy, functor);
}
@Override
void attachFunctor(AttachInfo attachInfo, long functor) {
nAttachFunctor(mNativeProxy, functor);
}
@Override
void setName(String name) {
}
@Override
protected void finalize() throws Throwable {
try {
nDeleteProxy(mNativeProxy);
} finally {
super.finalize();
}
}
/** @hide */
public static native void postToRenderThread(Runnable runnable);
private static native long nCreateProxy(boolean translucent);
private static native void nDeleteProxy(long nativeProxy);
private static native boolean nInitialize(long nativeProxy, Surface window);
private static native void nUpdateSurface(long nativeProxy, Surface window);
private static native void nSetup(long nativeProxy, int width, int height);
private static native void nDrawDisplayList(long nativeProxy, long displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
private static native void nDestroyCanvas(long nativeProxy);
private static native void nAttachFunctor(long nativeProxy, long functor);
private static native void nDetachFunctor(long nativeProxy, long functor);
}