android_view_Surface.cpp revision 3866f0d581ceaa165710feeee9f37fe1b0d7067d
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17fae5cb2b356a1fef172b43066180a7ab4c32dbacMathias Agopian#define LOG_TAG "Surface"
18fae5cb2b356a1fef172b43066180a7ab4c32dbacMathias Agopian
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
213866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian#include "jni.h"
223866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian#include "JNIHelp.h"
2364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown#include "android_os_Parcel.h"
24a111187a5b4dc5d287e29ced7d65e8d20edca140Dianne Hackborn#include "android/graphics/GraphicsJNI.h"
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
263866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian#include <android_runtime/AndroidRuntime.h>
273866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian#include <android_runtime/android_view_Surface.h>
283866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian#include <android_runtime/android_graphics_SurfaceTexture.h>
298335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
308335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
31d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden#include <gui/GLConsumer.h>
328335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Rect.h>
348335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <ui/Region.h>
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <SkCanvas.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <SkBitmap.h>
386158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian#include <SkRegion.h>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/misc.h>
419e316a1a2a8d734315bbd56a85308f9657a92913Jeff Brown#include <utils/Log.h>
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown#include <ScopedUtfChars.h>
4464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* const OutOfResourcesException =
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    "android/view/Surface$OutOfResourcesException";
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5264a55af0ac700baecb0877235eb42caac59a3560Jeff Brownstatic struct {
5364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jclass clazz;
543866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    jfieldID mNativeObject;
5564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID mGenerationId;
5664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID mCanvas;
577c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    jfieldID mCanvasSaveCount;
58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    jmethodID ctor;
5964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown} gSurfaceClassInfo;
6064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
6164a55af0ac700baecb0877235eb42caac59a3560Jeff Brownstatic struct {
6264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID left;
6364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID top;
6464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID right;
6564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID bottom;
6664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown} gRectClassInfo;
6764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
6864a55af0ac700baecb0877235eb42caac59a3560Jeff Brownstatic struct {
6964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID mNativeCanvas;
7064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jfieldID mSurfaceFormat;
7164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown} gCanvasClassInfo;
7264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7564a55af0ac700baecb0877235eb42caac59a3560Jeff Brownbool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
7664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
77050316184b01c0d1a01c46afae7429b89a27c31btedbo}
78050316184b01c0d1a01c46afae7429b89a27c31btedbo
793866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopiansp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
803866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    return android_view_Surface_getSurface(env, surfaceObj);
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
833866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopiansp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
843866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    return reinterpret_cast<Surface *>(
853866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeObject));
86cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown}
87cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
88cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownjobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env,
89d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer>& bufferProducer) {
90d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer == NULL) {
91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        return NULL;
92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
94d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<Surface> surface(new Surface(bufferProducer));
95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    if (surface == NULL) {
96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        return NULL;
97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
993866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor, surface.get());
100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    if (surfaceObj == NULL) {
101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        if (env->ExceptionCheck()) {
102d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden            ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            LOGE_EX(env);
104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            env->ExceptionClear();
105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        return NULL;
107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
1083866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    surface->incStrong(surfaceObj);
109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    return surfaceObj;
110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown}
111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1143866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic jint nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj,
11564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        jobject surfaceTextureObj) {
116d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<GLConsumer> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj));
1172e76c992bfa955cb637417005941e3e93810a99dDaniel Lam    if (st == NULL) {
1182e76c992bfa955cb637417005941e3e93810a99dDaniel Lam        jniThrowException(env, "java/lang/IllegalArgumentException",
1192e76c992bfa955cb637417005941e3e93810a99dDaniel Lam                "SurfaceTexture has already been released");
1203866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        return 0;
1212e76c992bfa955cb637417005941e3e93810a99dDaniel Lam    }
12264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
123d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bq = st->getBufferQueue();
1242e76c992bfa955cb637417005941e3e93810a99dDaniel Lam    sp<Surface> surface(new Surface(bq));
1250de171b0d490a5928d54d2fb67c912d140aac643Ted Bonkenburg    if (surface == NULL) {
1260de171b0d490a5928d54d2fb67c912d140aac643Ted Bonkenburg        jniThrowException(env, OutOfResourcesException, NULL);
1273866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        return 0;
1280de171b0d490a5928d54d2fb67c912d140aac643Ted Bonkenburg    }
1290de171b0d490a5928d54d2fb67c912d140aac643Ted Bonkenburg
1303866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    surface->incStrong(surfaceObj);
1313866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    return int(surface.get());
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1343866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
1353866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
1363866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sur->decStrong(surfaceObj);
1378138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen}
1388138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen
1393866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
1403866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
1413866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sur->decStrong(surfaceObj);
142402c34649f514669517c2208e35caa58ff8bb2b9Mathias Agopian}
143402c34649f514669517c2208e35caa58ff8bb2b9Mathias Agopian
1443866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
1453866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
1463866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    return Surface::isValid(sur) ? JNI_TRUE : JNI_FALSE;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1493866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
1503866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
1513866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    if (!Surface::isValid(sur)) {
152c14bacf1fb511472138eeb5dc84a9423fc003214Mathias Agopian        doThrowIAE(env);
15364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        return JNI_FALSE;
154c14bacf1fb511472138eeb5dc84a9423fc003214Mathias Agopian    }
15564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    int value = 0;
1563866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
157c14bacf1fb511472138eeb5dc84a9423fc003214Mathias Agopian    anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
15864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    return value;
159c14bacf1fb511472138eeb5dc84a9423fc003214Mathias Agopian}
160c14bacf1fb511472138eeb5dc84a9423fc003214Mathias Agopian
16164a55af0ac700baecb0877235eb42caac59a3560Jeff Brownstatic inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
162f1e5b0d4e5d0d2a78c234cd0cbd3005a74a79429Mathias Agopian    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        we can map to SkBitmap::kARGB_8888_Config, and optionally call
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    */
1668138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen    switch (format) {
1678138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
1708138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
1718138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
1728138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen    default:                        return SkBitmap::kNo_Config;
1738138cb49e47f9a9905a316a217757710185c66aaMarco Nelissen    }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1763866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject dirtyRectObj) {
1773866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
1783866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian
179fea12b87f2988f20ea87314c4a1b47e1a0f4d95eRomain Guy    if (!Surface::isValid(surface)) {
1808451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env);
18164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        return NULL;
182fea12b87f2988f20ea87314c4a1b47e1a0f4d95eRomain Guy    }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // get dirty region
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Region dirtyRegion;
18664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    if (dirtyRectObj) {
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Rect dirty;
18864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        dirty.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
18964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        dirty.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
19064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        dirty.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
19164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        dirty.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
1926158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian        if (!dirty.isEmpty()) {
1938451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            dirtyRegion.set(dirty);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
19664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Surface::SurfaceInfo info;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err = surface->lock(&info, &dirtyRegion);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err < 0) {
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* const exception = (err == NO_MEMORY) ?
20364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown                OutOfResourcesException :
20464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown                "java/lang/IllegalArgumentException";
2058451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        jniThrowException(env, exception, NULL);
20664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        return NULL;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Associate a SkCanvas object to this surface
21064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
21164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2137c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
2147c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkBitmap bitmap;
2161473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    ssize_t bpr = info.s * bytesPerPixel(info.format);
2171473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
218f1e5b0d4e5d0d2a78c234cd0cbd3005a74a79429Mathias Agopian    if (info.format == PIXEL_FORMAT_RGBX_8888) {
219f1e5b0d4e5d0d2a78c234cd0cbd3005a74a79429Mathias Agopian        bitmap.setIsOpaque(true);
220f1e5b0d4e5d0d2a78c234cd0cbd3005a74a79429Mathias Agopian    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (info.w > 0 && info.h > 0) {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bitmap.setPixels(info.bits);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // be safe with an empty bitmap.
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bitmap.setPixels(NULL);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2277c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    nativeCanvas->setBitmapDevice(bitmap);
2288451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
2296158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    SkRegion clipReg;
2306158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    if (dirtyRegion.isRect()) { // very common case
231a8a0aa8b922c45fb4633f51610f264a19f9bd825Mathias Agopian        const Rect b(dirtyRegion.getBounds());
2326158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian        clipReg.setRect(b.left, b.top, b.right, b.bottom);
2336158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    } else {
2346158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian        size_t count;
2356158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian        Rect const* r = dirtyRegion.getArray(&count);
2366158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian        while (count) {
2376158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
2386158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian            r++, count--;
2396158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian        }
2406158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    }
2416158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian
2426158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian    nativeCanvas->clipRegion(clipReg);
2438451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
2447c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    int saveCount = nativeCanvas->save();
2457c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount);
2467c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik
24764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    if (dirtyRectObj) {
2486158b1bf0364da1582468a98ec09d004ba99deecMathias Agopian        const Rect& bounds(dirtyRegion.getBounds());
24964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left);
25064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        env->SetIntField(dirtyRectObj, gRectClassInfo.top, bounds.top);
25164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        env->SetIntField(dirtyRectObj, gRectClassInfo.right, bounds.right);
25264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, bounds.bottom);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2548451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
25564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    return canvasObj;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2583866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject canvasObj) {
25964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
26064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    if (!env->IsSameObject(ownCanvasObj, canvasObj)) {
2618451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2648451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
2653866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
26664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    if (!Surface::isValid(surface)) {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
26864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // detach the canvas from the surface
2717c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
2727c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
2737c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount);
2747c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    nativeCanvas->restoreToCount(saveCount);
2757c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    nativeCanvas->setBitmapDevice(SkBitmap());
2767c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // unlock surface
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err = surface->unlockAndPost();
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err < 0) {
2818451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowIAE(env);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown// ----------------------------------------------------------------------------
28664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
2873866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic jint nativeCopyFrom(JNIEnv* env, jobject surfaceObj,
2883866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        jint nativeObject, jint surfaceControlNativeObj) {
28917f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian    /*
29017f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian     * This is used by the WindowManagerService just after constructing
29117f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian     * a Surface and is necessary for returning the Surface reference to
29217f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian     * the caller. At this point, we should only have a SurfaceControl.
29317f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian     */
294fae5cb2b356a1fef172b43066180a7ab4c32dbacMathias Agopian
2953866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
2963866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> other(ctrl->getSurface());
2973866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    if (other != NULL) {
2983866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        other->incStrong(surfaceObj);
2993866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    }
3003866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian
3013866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
3023866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    if (sur != NULL) {
3033866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        sur->decStrong(surfaceObj);
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3063866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    return int(other.get());
30761566cc1932468720a831ad5cbc68ee080d613c9Dianne Hackborn}
30861566cc1932468720a831ad5cbc68ee080d613c9Dianne Hackborn
3093866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic jint nativeReadFromParcel(JNIEnv* env, jobject surfaceObj,
3103866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        jint nativeObject, jobject parcelObj) {
31164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    Parcel* parcel = parcelForJavaObject(env, parcelObj);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (parcel == NULL) {
3138451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowNPE(env);
3143866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        return 0;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3163866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
3173866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    if (self != NULL) {
3183866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        self->decStrong(surfaceObj);
3193866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    }
3203866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> sur(Surface::readFromParcel(*parcel));
3213866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    if (sur != NULL) {
3223866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        sur->incStrong(surfaceObj);
3233866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    }
3243866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    return int(sur.get());
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3273866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianstatic void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj,
3283866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian        jint nativeObject, jobject parcelObj) {
32964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    Parcel* parcel = parcelForJavaObject(env, parcelObj);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (parcel == NULL) {
3318451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowNPE(env);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3343866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
3353866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    Surface::writeToParcel(self, parcel);
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gSurfaceMethods[] = {
3413866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)I",
34264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeCreateFromSurfaceTexture },
3433866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeRelease", "(I)V",
34464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeRelease },
3453866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeDestroy", "(I)V",
34664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeDestroy },
3473866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeIsValid", "(I)Z",
34864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeIsValid },
3493866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeIsConsumerRunningBehind", "(I)Z",
35064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeIsConsumerRunningBehind },
3513866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeLockCanvas", "(ILandroid/graphics/Rect;)Landroid/graphics/Canvas;",
35264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeLockCanvas },
3533866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V",
35464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeUnlockCanvasAndPost },
3553866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeCopyFrom", "(II)I",
35664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeCopyFrom },
3573866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeReadFromParcel", "(ILandroid/os/Parcel;)I",
35864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeReadFromParcel },
3593866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    {"nativeWriteToParcel", "(ILandroid/os/Parcel;)V",
36064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            (void*)nativeWriteToParcel },
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_view_Surface(JNIEnv* env)
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
36564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    int err = AndroidRuntime::registerNativeMethods(env, "android/view/Surface",
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            gSurfaceMethods, NELEM(gSurfaceMethods));
36764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
36864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    jclass clazz = env->FindClass("android/view/Surface");
36964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz));
3703866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    gSurfaceClassInfo.mNativeObject =
3713866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian            env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeObject", "I");
37264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gSurfaceClassInfo.mGenerationId =
37364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I");
37464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gSurfaceClassInfo.mCanvas =
37564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;");
3767c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik    gSurfaceClassInfo.mCanvasSaveCount =
3777c1a49f5f5ed6613d736464bf5001b777e89ced2Chris Craik            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I");
3783866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian    gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "(I)V");
37964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
38064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    clazz = env->FindClass("android/graphics/Canvas");
38164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
38264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
38364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
38464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    clazz = env->FindClass("android/graphics/Rect");
38564a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
38664a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gRectClassInfo.top = env->GetFieldID(clazz, "top", "I");
38764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gRectClassInfo.right = env->GetFieldID(clazz, "right", "I");
38864a55af0ac700baecb0877235eb42caac59a3560Jeff Brown    gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I");
38964a55af0ac700baecb0877235eb42caac59a3560Jeff Brown
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return err;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
394