summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/CalendarContract.java58
-rw-r--r--core/java/android/util/FinitePool.java21
-rw-r--r--libs/rs/Android.mk1
-rw-r--r--libs/rs/driver/rsdAllocation.cpp92
-rw-r--r--libs/rs/driver/rsdAllocation.h5
-rw-r--r--libs/rs/driver/rsdFrameBuffer.cpp138
-rw-r--r--libs/rs/driver/rsdFrameBufferObj.cpp143
-rw-r--r--libs/rs/driver/rsdFrameBufferObj.h59
-rw-r--r--libs/rs/driver/rsdGL.cpp2
-rw-r--r--libs/rs/driver/rsdGL.h2
-rw-r--r--libs/rs/driver/rsdMeshObj.cpp9
-rw-r--r--libs/rs/driver/rsdRuntimeStubs.cpp7
-rw-r--r--libs/rs/rsFBOCache.cpp10
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java8
-rw-r--r--tests/RenderScriptTests/FBOTest/AndroidManifest.xml11
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSync.java72
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncRS.java213
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncView.java144
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs233
-rw-r--r--tools/aapt/Command.cpp56
20 files changed, 1143 insertions, 141 deletions
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 98d9c8f..1a24716 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -648,7 +648,21 @@ public final class CalendarContract {
}
/**
- * Fields and helpers for interacting with Attendees.
+ * Fields and helpers for interacting with Attendees. Each row of this table
+ * represents a single attendee or guest of an event. Calling
+ * {@link #query(ContentResolver, long)} will return a list of attendees for
+ * the event with the given eventId. Both apps and sync adapters may write
+ * to this table. There are six writable fields and all of them except
+ * {@link #ATTENDEE_NAME} must be included when inserting a new attendee.
+ * They are:
+ * <ul>
+ * <li>{@link #EVENT_ID}</li>
+ * <li>{@link #ATTENDEE_NAME}</li>
+ * <li>{@link #ATTENDEE_EMAIL}</li>
+ * <li>{@link #ATTENDEE_RELATIONSHIP}</li>
+ * <li>{@link #ATTENDEE_TYPE}</li>
+ * <li>{@link #ATTENDEE_STATUS}</li>
+ * </ul>
*/
public static final class Attendees implements BaseColumns, AttendeesColumns, EventsColumns {
@@ -1446,7 +1460,8 @@ public final class CalendarContract {
/**
* Fields and helpers for interacting with Instances. An instance is a
* single occurrence of an event including time zone specific start and end
- * days and minutes.
+ * days and minutes. The instances table is not writable and only provides a
+ * way to query event occurrences.
*/
public static final class Instances implements BaseColumns, EventsColumns, CalendarsColumns {
@@ -1867,7 +1882,17 @@ public final class CalendarContract {
}
/**
- * Fields and helpers for accessing reminders for an event.
+ * Fields and helpers for accessing reminders for an event. Each row of this
+ * table represents a single reminder for an event. Calling
+ * {@link #query(ContentResolver, long)} will return a list of reminders for
+ * the event with the given eventId. Both apps and sync adapters may write
+ * to this table. There are three writable fields and all of them must be
+ * included when inserting a new reminder. They are:
+ * <ul>
+ * <li>{@link #EVENT_ID}</li>
+ * <li>{@link #MINUTES}</li>
+ * <li>{@link #METHOD}</li>
+ * </ul>
*/
public static final class Reminders implements BaseColumns, RemindersColumns, EventsColumns {
private static final String REMINDERS_WHERE = CalendarContract.Reminders.EVENT_ID + "=?";
@@ -1968,7 +1993,14 @@ public final class CalendarContract {
/**
* Fields and helpers for accessing calendar alerts information. These
- * fields are for tracking which alerts have been fired.
+ * fields are for tracking which alerts have been fired. Scheduled alarms
+ * will generate an intent using {@link #EVENT_REMINDER_ACTION}. Apps that
+ * receive this action may update the {@link #STATE} for the reminder when
+ * they have finished handling it. Apps that have their notifications
+ * disabled should not modify the table to ensure that they do not conflict
+ * with another app that is generating a notification. In general, apps
+ * should not need to write to this table directly except to update the
+ * state of a reminder.
*/
public static final class CalendarAlerts implements BaseColumns,
CalendarAlertsColumns, EventsColumns, CalendarsColumns {
@@ -2140,9 +2172,11 @@ public final class CalendarContract {
/**
* Schedules an alarm intent with the system AlarmManager that will
- * cause the Calendar provider to recheck alarms. This is used to wake
- * the Calendar alarm handler when an alarm is expected or to do a
- * periodic refresh of alarm data.
+ * notify listeners when a reminder should be fired. The provider will
+ * keep scheduled reminders up to date but apps may use this to
+ * implement snooze functionality without modifying the reminders table.
+ * Scheduled alarms will generate an intent using
+ * {@link #EVENT_REMINDER_ACTION}.
*
* @param context A context for referencing system resources
* @param manager The AlarmManager to use or null
@@ -2232,7 +2266,13 @@ public final class CalendarContract {
/**
* Fields for accessing the Extended Properties. This is a generic set of
* name/value pairs for use by sync adapters or apps to add extra
- * information to events.
+ * information to events. There are three writable columns and all three
+ * must be present when inserting a new value. They are:
+ * <ul>
+ * <li>{@link #EVENT_ID}</li>
+ * <li>{@link #NAME}</li>
+ * <li>{@link #VALUE}</li>
+ * </ul>
*/
public static final class ExtendedProperties implements BaseColumns,
ExtendedPropertiesColumns, EventsColumns {
@@ -2266,6 +2306,8 @@ public final class CalendarContract {
/**
* Columns from the EventsRawTimes table
+ *
+ * @hide
*/
protected interface EventsRawTimesColumns {
/**
diff --git a/core/java/android/util/FinitePool.java b/core/java/android/util/FinitePool.java
index 4ae21ad..b30f2bf 100644
--- a/core/java/android/util/FinitePool.java
+++ b/core/java/android/util/FinitePool.java
@@ -20,6 +20,8 @@ package android.util;
* @hide
*/
class FinitePool<T extends Poolable<T>> implements Pool<T> {
+ private static final String LOG_TAG = "FinitePool";
+
/**
* Factory used to create new pool objects
*/
@@ -77,15 +79,16 @@ class FinitePool<T extends Poolable<T>> implements Pool<T> {
}
public void release(T element) {
- if (element.isPooled()) {
- throw new IllegalArgumentException("Element already in the pool.");
- }
- if (mInfinite || mPoolCount < mLimit) {
- mPoolCount++;
- element.setNextPoolable(mRoot);
- element.setPooled(true);
- mRoot = element;
+ if (!element.isPooled()) {
+ if (mInfinite || mPoolCount < mLimit) {
+ mPoolCount++;
+ element.setNextPoolable(mRoot);
+ element.setPooled(true);
+ mRoot = element;
+ }
+ mManager.onReleased(element);
+ } else {
+ Log.w(LOG_TAG, "Element is already in pool: " + element);
}
- mManager.onReleased(element);
}
}
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 9fabf8d..d9cc6b6 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -119,6 +119,7 @@ LOCAL_SRC_FILES:= \
driver/rsdBcc.cpp \
driver/rsdCore.cpp \
driver/rsdFrameBuffer.cpp \
+ driver/rsdFrameBufferObj.cpp \
driver/rsdGL.cpp \
driver/rsdMesh.cpp \
driver/rsdMeshObj.cpp \
diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp
index 8bfc185..01a0cf6 100644
--- a/libs/rs/driver/rsdAllocation.cpp
+++ b/libs/rs/driver/rsdAllocation.cpp
@@ -19,6 +19,7 @@
#include "rsdBcc.h"
#include "rsdRuntime.h"
#include "rsdAllocation.h"
+#include "rsdFrameBufferObj.h"
#include "rsAllocation.h"
@@ -244,6 +245,9 @@ bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
drv->uploadDeferred = true;
}
+
+ drv->readBackFBO = NULL;
+
return true;
}
@@ -269,6 +273,10 @@ void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
free(drv->mallocPtr);
drv->mallocPtr = NULL;
}
+ if (drv->readBackFBO != NULL) {
+ delete drv->readBackFBO;
+ drv->readBackFBO = NULL;
+ }
free(drv);
alloc->mHal.drv = NULL;
}
@@ -292,13 +300,52 @@ void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
}
}
+static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) {
+ if (!alloc->getIsScript()) {
+ return; // nothing to sync
+ }
+
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer;
+
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+ if (!drv->textureID && !drv->renderTargetID) {
+ return; // nothing was rendered here yet, so nothing to sync
+ }
+ if (drv->readBackFBO == NULL) {
+ drv->readBackFBO = new RsdFrameBufferObj();
+ drv->readBackFBO->setColorTarget(drv, 0);
+ drv->readBackFBO->setDimensions(alloc->getType()->getDimX(),
+ alloc->getType()->getDimY());
+ }
+
+ // Bind the framebuffer object so we can read back from it
+ drv->readBackFBO->setActive(rsc);
+
+ // Do the readback
+ glReadPixels(0, 0, alloc->getType()->getDimX(), alloc->getType()->getDimY(),
+ drv->glFormat, drv->glType, alloc->getPtr());
+
+ // Revert framebuffer to its original
+ lastFbo->setActive(rsc);
+}
void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
RsAllocationUsageType src) {
DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
- if (!drv->uploadDeferred) {
+ if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
+ if(!alloc->getIsRenderTarget()) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER,
+ "Attempting to sync allocation from render target, "
+ "for non-render target allocation");
+ } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA"
+ "render target");
+ } else {
+ rsdAllocationSyncFromFBO(rsc, alloc);
+ }
return;
}
@@ -382,7 +429,40 @@ void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
const android::renderscript::Allocation *dstAlloc,
uint32_t dstXoff, uint32_t dstLod, uint32_t count,
const android::renderscript::Allocation *srcAlloc,
- uint32_t srcXoff, uint32_t srcLod){
+ uint32_t srcXoff, uint32_t srcLod) {
+}
+
+uint8_t *getOffsetPtr(const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t lod,
+ RsAllocationCubemapFace face) {
+ uint8_t *ptr = static_cast<uint8_t *>(alloc->getPtr());
+ ptr += alloc->getType()->getLODOffset(lod, xoff, yoff);
+
+ if (face != 0) {
+ uint32_t totalSizeBytes = alloc->getType()->getSizeBytes();
+ uint32_t faceOffset = totalSizeBytes / 6;
+ ptr += faceOffset * (uint32_t)face;
+ }
+ return ptr;
+}
+
+
+void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
+ RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
+ const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+ RsAllocationCubemapFace srcFace) {
+ uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
+ for (uint32_t i = 0; i < h; i ++) {
+ uint8_t *dstPtr = getOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace);
+ uint8_t *srcPtr = getOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace);
+ memcpy(dstPtr, srcPtr, w * elementSize);
+
+ LOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
+ dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
+ }
}
void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
@@ -392,6 +472,14 @@ void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
const android::renderscript::Allocation *srcAlloc,
uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
RsAllocationCubemapFace srcFace) {
+ if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
+ "yet implemented.");
+ return;
+ }
+ rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff,
+ dstLod, dstFace, w, h, srcAlloc,
+ srcXoff, srcYoff, srcLod, srcFace);
}
void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
diff --git a/libs/rs/driver/rsdAllocation.h b/libs/rs/driver/rsdAllocation.h
index 7555c4a..4fc4419 100644
--- a/libs/rs/driver/rsdAllocation.h
+++ b/libs/rs/driver/rsdAllocation.h
@@ -23,6 +23,8 @@
#include <GLES/gl.h>
#include <GLES2/gl2.h>
+class RsdFrameBufferObj;
+
struct DrvAllocation {
// Is this a legal structure to be used as a texture source.
// Initially this will require 1D or 2D and color data
@@ -42,8 +44,9 @@ struct DrvAllocation {
GLenum glType;
GLenum glFormat;
-
bool uploadDeferred;
+
+ RsdFrameBufferObj * readBackFBO;
};
GLenum rsdTypeToGLType(RsDataType t);
diff --git a/libs/rs/driver/rsdFrameBuffer.cpp b/libs/rs/driver/rsdFrameBuffer.cpp
index ce72b5d..8c1b12d 100644
--- a/libs/rs/driver/rsdFrameBuffer.cpp
+++ b/libs/rs/driver/rsdFrameBuffer.cpp
@@ -17,6 +17,7 @@
#include "rsdCore.h"
#include "rsdFrameBuffer.h"
+#include "rsdFrameBufferObj.h"
#include "rsdAllocation.h"
#include "rsContext.h"
@@ -28,133 +29,70 @@
using namespace android;
using namespace android::renderscript;
-struct DrvFrameBuffer {
- GLuint mFBOId;
-};
-
-void checkError(const Context *rsc) {
- GLenum status;
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- switch (status) {
- case GL_FRAMEBUFFER_COMPLETE:
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- rsc->setError(RS_ERROR_BAD_VALUE,
- "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- rsc->setError(RS_ERROR_BAD_VALUE,
- "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- rsc->setError(RS_ERROR_BAD_VALUE,
- "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED:
- rsc->setError(RS_ERROR_BAD_VALUE,
- "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
- break;
- }
-}
-
-
void setDepthAttachment(const Context *rsc, const FBOCache *fb) {
+ RsdFrameBufferObj *fbo = (RsdFrameBufferObj*)fb->mHal.drv;
+
+ DrvAllocation *depth = NULL;
if (fb->mHal.state.depthTarget.get() != NULL) {
- DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.depthTarget->mHal.drv;
-
- if (drv->textureID) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_TEXTURE_2D, drv->textureID, 0);
- } else {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, drv->renderTargetID);
+ depth = (DrvAllocation *)fb->mHal.state.depthTarget->mHal.drv;
+
+ if (depth->uploadDeferred) {
+ rsdAllocationSyncAll(rsc, fb->mHal.state.depthTarget.get(),
+ RS_ALLOCATION_USAGE_SCRIPT);
}
- } else {
- // Reset last attachment
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
}
+ fbo->setDepthTarget(depth);
}
void setColorAttachment(const Context *rsc, const FBOCache *fb) {
+ RsdFrameBufferObj *fbo = (RsdFrameBufferObj*)fb->mHal.drv;
// Now attach color targets
for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
- uint32_t texID = 0;
+ DrvAllocation *color = NULL;
if (fb->mHal.state.colorTargets[i].get() != NULL) {
- DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.colorTargets[i]->mHal.drv;
-
- if (drv->textureID) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
- GL_TEXTURE_2D, drv->textureID, 0);
- } else {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
- GL_RENDERBUFFER, drv->renderTargetID);
- }
- } else {
- // Reset last attachment
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
- GL_RENDERBUFFER, 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
- GL_TEXTURE_2D, 0, 0);
- }
- }
-}
-
-bool renderToFramebuffer(const FBOCache *fb) {
- if (fb->mHal.state.depthTarget.get() != NULL) {
- return false;
- }
+ color = (DrvAllocation *)fb->mHal.state.colorTargets[i]->mHal.drv;
- for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
- if (fb->mHal.state.colorTargets[i].get() != NULL) {
- return false;
+ if (color->uploadDeferred) {
+ rsdAllocationSyncAll(rsc, fb->mHal.state.colorTargets[i].get(),
+ RS_ALLOCATION_USAGE_SCRIPT);
+ }
}
+ fbo->setColorTarget(color, i);
}
- return true;
}
-
bool rsdFrameBufferInit(const Context *rsc, const FBOCache *fb) {
- DrvFrameBuffer *drv = (DrvFrameBuffer *)calloc(1, sizeof(DrvFrameBuffer));
- if (drv == NULL) {
+ RsdFrameBufferObj *fbo = new RsdFrameBufferObj();
+ if (fbo == NULL) {
return false;
}
- fb->mHal.drv = drv;
- drv->mFBOId = 0;
+ fb->mHal.drv = fbo;
+
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ dc->gl.currentFrameBuffer = fbo;
return true;
}
void rsdFrameBufferSetActive(const Context *rsc, const FBOCache *fb) {
- DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
-
- bool framebuffer = renderToFramebuffer(fb);
- if (!framebuffer) {
- if(drv->mFBOId == 0) {
- glGenFramebuffers(1, &drv->mFBOId);
- }
- glBindFramebuffer(GL_FRAMEBUFFER, drv->mFBOId);
-
- setDepthAttachment(rsc, fb);
- setColorAttachment(rsc, fb);
-
- glViewport(0, 0, fb->mHal.state.colorTargets[0]->getType()->getDimX(),
- fb->mHal.state.colorTargets[0]->getType()->getDimY());
-
- checkError(rsc);
- } else {
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
+ setDepthAttachment(rsc, fb);
+ setColorAttachment(rsc, fb);
+
+ RsdFrameBufferObj *fbo = (RsdFrameBufferObj *)fb->mHal.drv;
+ if (fb->mHal.state.colorTargets[0].get()) {
+ fbo->setDimensions(fb->mHal.state.colorTargets[0]->getType()->getDimX(),
+ fb->mHal.state.colorTargets[0]->getType()->getDimY());
+ } else if (fb->mHal.state.depthTarget.get()) {
+ fbo->setDimensions(fb->mHal.state.depthTarget->getType()->getDimX(),
+ fb->mHal.state.depthTarget->getType()->getDimY());
}
+
+ fbo->setActive(rsc);
}
void rsdFrameBufferDestroy(const Context *rsc, const FBOCache *fb) {
- DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
- if(drv->mFBOId != 0) {
- glDeleteFramebuffers(1, &drv->mFBOId);
- }
-
- free(fb->mHal.drv);
+ RsdFrameBufferObj *fbo = (RsdFrameBufferObj *)fb->mHal.drv;
+ delete fbo;
fb->mHal.drv = NULL;
}
diff --git a/libs/rs/driver/rsdFrameBufferObj.cpp b/libs/rs/driver/rsdFrameBufferObj.cpp
new file mode 100644
index 0000000..145bf34
--- /dev/null
+++ b/libs/rs/driver/rsdFrameBufferObj.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+
+#include "rsdFrameBufferObj.h"
+#include "rsdAllocation.h"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+RsdFrameBufferObj::RsdFrameBufferObj() {
+ mFBOId = 0;
+ mWidth = 0;
+ mHeight = 0;
+ mColorTargetsCount = 1;
+ mColorTargets = new DrvAllocation*[mColorTargetsCount];
+ for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
+ mColorTargets[i] = 0;
+ }
+ mDepthTarget = NULL;
+ mDirty = true;
+}
+
+RsdFrameBufferObj::~RsdFrameBufferObj() {
+ if(mFBOId != 0) {
+ glDeleteFramebuffers(1, &mFBOId);
+ }
+ delete [] mColorTargets;
+}
+
+void RsdFrameBufferObj::checkError(const Context *rsc) {
+ GLenum status;
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ switch (status) {
+ case GL_FRAMEBUFFER_COMPLETE:
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ rsc->setError(RS_ERROR_BAD_VALUE,
+ "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
+ break;
+ }
+}
+
+
+void RsdFrameBufferObj::setDepthAttachment() {
+ if (mDepthTarget != NULL) {
+ if (mDepthTarget->textureID) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D, mDepthTarget->textureID, 0);
+ } else {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, mDepthTarget->renderTargetID);
+ }
+ } else {
+ // Reset last attachment
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
+ }
+}
+
+void RsdFrameBufferObj::setColorAttachment() {
+ // Now attach color targets
+ for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
+ if (mColorTargets[i] != NULL) {
+ if (mColorTargets[i]->textureID) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_TEXTURE_2D, mColorTargets[i]->textureID, 0);
+ } else {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_RENDERBUFFER, mColorTargets[i]->renderTargetID);
+ }
+ } else {
+ // Reset last attachment
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_RENDERBUFFER, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+ GL_TEXTURE_2D, 0, 0);
+ }
+ }
+}
+
+bool RsdFrameBufferObj::renderToFramebuffer() {
+ if (mDepthTarget != NULL) {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < mColorTargetsCount; i ++) {
+ if (mColorTargets[i] != NULL) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void RsdFrameBufferObj::setActive(const Context *rsc) {
+ bool framebuffer = renderToFramebuffer();
+ if (!framebuffer) {
+ if(mFBOId == 0) {
+ glGenFramebuffers(1, &mFBOId);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBOId);
+
+ if (mDirty) {
+ setDepthAttachment();
+ setColorAttachment();
+ mDirty = false;
+ }
+
+ glViewport(0, 0, mWidth, mHeight);
+ checkError(rsc);
+ } else {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
+ }
+}
diff --git a/libs/rs/driver/rsdFrameBufferObj.h b/libs/rs/driver/rsdFrameBufferObj.h
new file mode 100644
index 0000000..c6e7deb
--- /dev/null
+++ b/libs/rs/driver/rsdFrameBufferObj.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _RSD_FRAMEBUFFER_OBJ_H_
+#define _RSD_FRAMEBUFFER_OBJ_H_
+
+#include <rsContext.h>
+
+class DrvAllocation;
+
+class RsdFrameBufferObj {
+public:
+ RsdFrameBufferObj();
+ ~RsdFrameBufferObj();
+
+ void setActive(const android::renderscript::Context *rsc);
+ void setColorTarget(DrvAllocation *color, uint32_t index) {
+ mColorTargets[index] = color;
+ mDirty = true;
+ }
+ void setDepthTarget(DrvAllocation *depth) {
+ mDepthTarget = depth;
+ mDirty = true;
+ }
+ void setDimensions(uint32_t width, uint32_t height) {
+ mWidth = width;
+ mHeight = height;
+ }
+protected:
+ uint32_t mFBOId;
+ DrvAllocation **mColorTargets;
+ uint32_t mColorTargetsCount;
+ DrvAllocation *mDepthTarget;
+
+ uint32_t mWidth;
+ uint32_t mHeight;
+
+ bool mDirty;
+
+ bool renderToFramebuffer();
+ void checkError(const android::renderscript::Context *rsc);
+ void setColorAttachment();
+ void setDepthAttachment();
+};
+
+#endif //_RSD_FRAMEBUFFER_STATE_H_
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index a70589b..3ff03b4 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -39,6 +39,7 @@
#include "rsContext.h"
#include "rsdShaderCache.h"
#include "rsdVertexArray.h"
+#include "rsdFrameBufferObj.h"
using namespace android;
using namespace android::renderscript;
@@ -294,6 +295,7 @@ bool rsdGLInit(const Context *rsc) {
dc->gl.shaderCache = new RsdShaderCache();
dc->gl.vertexArrayState = new RsdVertexArrayState();
dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
+ dc->gl.currentFrameBuffer = NULL;
LOGV("initGLThread end %p", rsc);
return true;
diff --git a/libs/rs/driver/rsdGL.h b/libs/rs/driver/rsdGL.h
index 01c8438..0d5b7e7 100644
--- a/libs/rs/driver/rsdGL.h
+++ b/libs/rs/driver/rsdGL.h
@@ -22,6 +22,7 @@
class RsdShaderCache;
class RsdVertexArrayState;
+class RsdFrameBufferObj;
typedef void (* InvokeFunc_t)(void);
typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
@@ -68,6 +69,7 @@ typedef struct RsdGLRec {
uint32_t height;
RsdShaderCache *shaderCache;
RsdVertexArrayState *vertexArrayState;
+ RsdFrameBufferObj *currentFrameBuffer;
} RsdGL;
diff --git a/libs/rs/driver/rsdMeshObj.cpp b/libs/rs/driver/rsdMeshObj.cpp
index c220ac1..4315c0d 100644
--- a/libs/rs/driver/rsdMeshObj.cpp
+++ b/libs/rs/driver/rsdMeshObj.cpp
@@ -138,7 +138,10 @@ void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, ui
for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
const Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[ct].get();
- rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT);
+ DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
+ if (drv->uploadDeferred) {
+ rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT);
+ }
}
// update attributes with either buffer information or data ptr based on their current state
@@ -163,7 +166,9 @@ void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, ui
const Allocation *idxAlloc = prim->mIndexBuffer.get();
if (idxAlloc) {
DrvAllocation *drvAlloc = (DrvAllocation *)idxAlloc->mHal.drv;
- rsdAllocationSyncAll(rsc, idxAlloc, RS_ALLOCATION_USAGE_SCRIPT);
+ if (drvAlloc->uploadDeferred) {
+ rsdAllocationSyncAll(rsc, idxAlloc, RS_ALLOCATION_USAGE_SCRIPT);
+ }
if (drvAlloc->bufferID) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drvAlloc->bufferID);
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index bd8b3c3..25302aa 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -95,6 +95,8 @@ static void SC_AllocationCopy1DRange(Allocation *dstAlloc,
Allocation *srcAlloc,
uint32_t srcOff, uint32_t srcMip) {
GET_TLS();
+ rsrAllocationCopy1DRange(rsc, dstAlloc, dstOff, dstMip, count,
+ srcAlloc, srcOff, srcMip);
}
static void SC_AllocationCopy2DRange(Allocation *dstAlloc,
@@ -105,6 +107,11 @@ static void SC_AllocationCopy2DRange(Allocation *dstAlloc,
uint32_t srcXoff, uint32_t srcYoff,
uint32_t srcMip, uint32_t srcFace) {
GET_TLS();
+ rsrAllocationCopy2DRange(rsc, dstAlloc,
+ dstXoff, dstYoff, dstMip, dstFace,
+ width, height,
+ srcAlloc,
+ srcXoff, srcYoff, srcMip, srcFace);
}
diff --git a/libs/rs/rsFBOCache.cpp b/libs/rs/rsFBOCache.cpp
index 6960ef2..c5c64c2 100644
--- a/libs/rs/rsFBOCache.cpp
+++ b/libs/rs/rsFBOCache.cpp
@@ -80,16 +80,6 @@ void FBOCache::setup(Context *rsc) {
return;
}
- if (mHal.state.depthTarget.get() != NULL) {
- mHal.state.depthTarget->syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
- }
-
- for (uint32_t i = 0; i < mHal.state.colorTargetsCount; i ++) {
- if (mHal.state.colorTargets[i].get() != NULL) {
- mHal.state.colorTargets[i]->syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT);
- }
- }
-
rsc->mHal.funcs.framebuffer.setActive(rsc, this);
mDirty = false;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index ec59da6..a9dfb22 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -441,6 +441,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (oldService != null) {
tryRemoveServiceLocked(oldService);
}
+ // This API is intended for testing so enable accessibility to make
+ // sure clients can start poking with the window content.
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED, 1);
+ // Also disable all accessibility services to avoid interference
+ // with the tests.
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
}
AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
diff --git a/tests/RenderScriptTests/FBOTest/AndroidManifest.xml b/tests/RenderScriptTests/FBOTest/AndroidManifest.xml
index c2e0cc6..788e856 100644
--- a/tests/RenderScriptTests/FBOTest/AndroidManifest.xml
+++ b/tests/RenderScriptTests/FBOTest/AndroidManifest.xml
@@ -3,11 +3,20 @@
package="com.android.fbotest">
<application android:label="_FBOTest">
<activity android:name="FBOTest"
+ android:label="FBO Base Test"
android:theme="@android:style/Theme.Black.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
- </activity>
+ </activity>
+ <activity android:name="FBOSync"
+ android:label="FBO Sync Test"
+ android:theme="@android:style/Theme.Black.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSync.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSync.java
new file mode 100644
index 0000000..d30ad7e
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSync.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 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 com.android.fbotest;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.MenuInflater;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+import android.net.Uri;
+
+import java.lang.Runtime;
+
+public class FBOSync extends Activity {
+
+ private FBOSyncView mView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mView = new FBOSyncView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mView.resume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mView.pause();
+ }
+}
+
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncRS.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncRS.java
new file mode 100644
index 0000000..57a117c
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncRS.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2011 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 com.android.fbotest;
+
+import java.io.Writer;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Element.DataType;
+import android.renderscript.Element.DataKind;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.Type.Builder;
+import android.util.Log;
+
+
+public class FBOSyncRS {
+
+ public FBOSyncRS() {
+ }
+
+ public void init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ initRS();
+ }
+
+ public void surfaceChanged() {
+ mRS.getWidth();
+ mRS.getHeight();
+ }
+
+ private Resources mRes;
+ private RenderScriptGL mRS;
+ private Sampler mSampler;
+ private ProgramStore mPSBackground;
+ private ProgramFragment mPFBackground;
+ private ProgramVertex mPVBackground;
+ private ProgramVertexFixedFunction.Constants mPVA;
+
+ private Allocation mGridImage;
+ private Allocation mOffscreen;
+ private Allocation mOffscreenDepth;
+ private Allocation mAllocPV;
+ private Allocation mReadBackTest;
+
+ private Font mItalic;
+ private Allocation mTextAlloc;
+
+ private ScriptField_MeshInfo mMeshes;
+ private ScriptC_fbosync mScript;
+
+
+ public void onActionDown(float x, float y) {
+ mScript.invoke_onActionDown(x, y);
+ }
+
+ public void onActionScale(float scale) {
+ mScript.invoke_onActionScale(scale);
+ }
+
+ public void onActionMove(float x, float y) {
+ mScript.invoke_onActionMove(x, y);
+ }
+
+ private void initPFS() {
+ ProgramStore.Builder b = new ProgramStore.Builder(mRS);
+
+ b.setDepthFunc(ProgramStore.DepthFunc.LESS);
+ b.setDitherEnabled(false);
+ b.setDepthMaskEnabled(true);
+ mPSBackground = b.create();
+
+ mScript.set_gPFSBackground(mPSBackground);
+ }
+
+ private void initPF() {
+ Sampler.Builder bs = new Sampler.Builder(mRS);
+ bs.setMinification(Sampler.Value.LINEAR);
+ bs.setMagnification(Sampler.Value.LINEAR);
+ bs.setWrapS(Sampler.Value.CLAMP);
+ bs.setWrapT(Sampler.Value.CLAMP);
+ mSampler = bs.create();
+
+ ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS);
+ b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+ mPFBackground = b.create();
+ mPFBackground.bindSampler(mSampler, 0);
+
+ mScript.set_gPFBackground(mPFBackground);
+ }
+
+ private void initPV() {
+ ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ mPVBackground = pvb.create();
+
+ mPVA = new ProgramVertexFixedFunction.Constants(mRS);
+ ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA);
+
+ mScript.set_gPVBackground(mPVBackground);
+ }
+
+ private void loadImage() {
+ mGridImage = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ mScript.set_gTGrid(mGridImage);
+ }
+
+ private void initTextAllocation(String fileName) {
+ String allocString = "Displaying file: " + fileName;
+ mTextAlloc = Allocation.createFromString(mRS, allocString, Allocation.USAGE_SCRIPT);
+ mScript.set_gTextAlloc(mTextAlloc);
+ }
+
+ private void initMeshes(FileA3D model) {
+ int numEntries = model.getIndexEntryCount();
+ int numMeshes = 0;
+ for (int i = 0; i < numEntries; i ++) {
+ FileA3D.IndexEntry entry = model.getIndexEntry(i);
+ if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+ numMeshes ++;
+ }
+ }
+
+ if (numMeshes > 0) {
+ mMeshes = new ScriptField_MeshInfo(mRS, numMeshes);
+
+ for (int i = 0; i < numEntries; i ++) {
+ FileA3D.IndexEntry entry = model.getIndexEntry(i);
+ if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+ Mesh mesh = entry.getMesh();
+ mMeshes.set_mMesh(i, mesh, false);
+ mMeshes.set_mNumIndexSets(i, mesh.getPrimitiveCount(), false);
+ }
+ }
+ mMeshes.copyAll();
+ } else {
+ throw new RSRuntimeException("No valid meshes in file");
+ }
+
+ mScript.bind_gMeshes(mMeshes);
+ mScript.invoke_updateMeshInfo();
+ }
+
+ public void loadA3DFile(String path) {
+ FileA3D model = FileA3D.createFromFile(mRS, path);
+ initMeshes(model);
+ initTextAllocation(path);
+ }
+
+ private void initRS() {
+
+ mScript = new ScriptC_fbosync(mRS, mRes, R.raw.fbosync);
+
+ initPFS();
+ initPF();
+ initPV();
+
+ loadImage();
+
+ Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+ b.setX(512).setY(512);
+ mOffscreen = Allocation.createTyped(mRS,
+ b.create(),
+ Allocation.USAGE_SCRIPT |
+ Allocation.USAGE_GRAPHICS_TEXTURE |
+ Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+ mScript.set_gOffscreen(mOffscreen);
+
+ mReadBackTest = Allocation.createTyped(mRS,
+ b.create(),
+ Allocation.USAGE_SCRIPT |
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ mScript.set_gReadBackTest(mReadBackTest);
+
+ b = new Type.Builder(mRS,
+ Element.createPixel(mRS, DataType.UNSIGNED_16,
+ DataKind.PIXEL_DEPTH));
+ b.setX(512).setY(512);
+ mOffscreenDepth = Allocation.createTyped(mRS,
+ b.create(),
+ Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+ mScript.set_gOffscreenDepth(mOffscreenDepth);
+
+ FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
+ initMeshes(model);
+
+ mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8);
+ mScript.set_gItalic(mItalic);
+
+ initTextAllocation("R.raw.robot");
+
+ mRS.bindRootScript(mScript);
+ }
+}
+
+
+
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncView.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncView.java
new file mode 100644
index 0000000..6a85628
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncView.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2011 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 com.android.fbotest;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.ScaleGestureDetector;
+import android.util.Log;
+
+public class FBOSyncView extends RSSurfaceView {
+
+ private RenderScriptGL mRS;
+ private FBOSyncRS mRender;
+
+ private ScaleGestureDetector mScaleDetector;
+
+ private static final int INVALID_POINTER_ID = -1;
+ private int mActivePointerId = INVALID_POINTER_ID;
+
+ public FBOSyncView(Context context) {
+ super(context);
+ ensureRenderScript();
+ mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
+ }
+
+ private void ensureRenderScript() {
+ if (mRS == null) {
+ RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+ sc.setDepth(16, 24);
+ mRS = createRenderScriptGL(sc);
+ mRender = new FBOSyncRS();
+ mRender.init(mRS, getResources());
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ ensureRenderScript();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+ mRender.surfaceChanged();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mRender = null;
+ if (mRS != null) {
+ mRS = null;
+ destroyRenderScriptGL();
+ }
+ }
+
+ public void loadA3DFile(String path) {
+ mRender.loadA3DFile(path);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ mScaleDetector.onTouchEvent(ev);
+
+ boolean ret = false;
+ float x = ev.getX();
+ float y = ev.getY();
+
+ final int action = ev.getAction();
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ mRender.onActionDown(x, y);
+ mActivePointerId = ev.getPointerId(0);
+ ret = true;
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (!mScaleDetector.isInProgress()) {
+ mRender.onActionMove(x, y);
+ }
+ mRender.onActionDown(x, y);
+ ret = true;
+ break;
+ }
+
+ case MotionEvent.ACTION_UP: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ final int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ x = ev.getX(newPointerIndex);
+ y = ev.getY(newPointerIndex);
+ mRender.onActionDown(x, y);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ }
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+ private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ mRender.onActionScale(detector.getScaleFactor());
+ return true;
+ }
+ }
+}
+
+
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs
new file mode 100644
index 0000000..b77ccb4
--- /dev/null
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs
@@ -0,0 +1,233 @@
+// Copyright (C) 2011 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.fbotest)
+
+#include "rs_graphics.rsh"
+
+rs_program_vertex gPVBackground;
+rs_program_fragment gPFBackground;
+
+rs_allocation gTGrid;
+
+rs_program_store gPFSBackground;
+
+rs_font gItalic;
+rs_allocation gTextAlloc;
+
+rs_allocation gOffscreen;
+rs_allocation gOffscreenDepth;
+rs_allocation gReadBackTest;
+
+typedef struct MeshInfo {
+ rs_mesh mMesh;
+ int mNumIndexSets;
+ float3 bBoxMin;
+ float3 bBoxMax;
+} MeshInfo_t;
+
+MeshInfo_t *gMeshes;
+
+static float3 gLookAt;
+
+static float gRotateX;
+static float gRotateY;
+static float gZoom;
+
+static float gLastX;
+static float gLastY;
+
+void onActionDown(float x, float y) {
+ gLastX = x;
+ gLastY = y;
+}
+
+void onActionScale(float scale) {
+
+ gZoom *= 1.0f / scale;
+ gZoom = max(0.1f, min(gZoom, 500.0f));
+}
+
+void onActionMove(float x, float y) {
+ float dx = gLastX - x;
+ float dy = gLastY - y;
+
+ if (fabs(dy) <= 2.0f) {
+ dy = 0.0f;
+ }
+ if (fabs(dx) <= 2.0f) {
+ dx = 0.0f;
+ }
+
+ gRotateY -= dx;
+ if (gRotateY > 360) {
+ gRotateY -= 360;
+ }
+ if (gRotateY < 0) {
+ gRotateY += 360;
+ }
+
+ gRotateX -= dy;
+ gRotateX = min(gRotateX, 80.0f);
+ gRotateX = max(gRotateX, -80.0f);
+
+ gLastX = x;
+ gLastY = y;
+}
+
+void init() {
+ gRotateX = 0.0f;
+ gRotateY = 0.0f;
+ gZoom = 50.0f;
+ gLookAt = 0.0f;
+}
+
+void updateMeshInfo() {
+ rs_allocation allMeshes = rsGetAllocation(gMeshes);
+ int size = rsAllocationGetDimX(allMeshes);
+ gLookAt = 0.0f;
+ float minX, minY, minZ, maxX, maxY, maxZ;
+ for (int i = 0; i < size; i++) {
+ MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
+ rsgMeshComputeBoundingBox(info->mMesh,
+ &minX, &minY, &minZ,
+ &maxX, &maxY, &maxZ);
+ info->bBoxMin = (minX, minY, minZ);
+ info->bBoxMax = (maxX, maxY, maxZ);
+ gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f;
+ }
+ gLookAt = gLookAt / (float)size;
+}
+
+static void renderAllMeshes() {
+ rs_allocation allMeshes = rsGetAllocation(gMeshes);
+ int size = rsAllocationGetDimX(allMeshes);
+ gLookAt = 0.0f;
+ float minX, minY, minZ, maxX, maxY, maxZ;
+ for (int i = 0; i < size; i++) {
+ MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
+ rsgDrawMesh(info->mMesh);
+ }
+}
+
+static void drawDescription() {
+ uint width = rsgGetWidth();
+ uint height = rsgGetHeight();
+ int left = 0, right = 0, top = 0, bottom = 0;
+
+ rsgBindFont(gItalic);
+
+ rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom);
+ rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom);
+}
+
+static void renderOffscreen(bool useDepth) {
+
+ rsgBindColorTarget(gOffscreen, 0);
+ if (useDepth) {
+ rsgBindDepthTarget(gOffscreenDepth);
+ rsgClearDepth(1.0f);
+ } else {
+ rsgClearDepthTarget();
+ }
+ rsgClearColor(0.8f, 0.0f, 0.0f, 1.0f);
+
+ rsgBindProgramVertex(gPVBackground);
+ rs_matrix4x4 proj;
+ float aspect = (float)rsAllocationGetDimX(gOffscreen) / (float)rsAllocationGetDimY(gOffscreen);
+ rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindProgramStore(gPFSBackground);
+ rsgBindTexture(gPFBackground, 0, gTGrid);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ // Position our models on the screen
+ rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom);
+ rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ renderAllMeshes();
+
+ // Render into the frambuffer
+ rsgClearAllRenderTargets();
+}
+
+static void drawOffscreenResult(int posX, int posY, rs_allocation texture) {
+ // display the result
+ rs_matrix4x4 proj, matrix;
+ rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+ rsMatrixLoadIdentity(&matrix);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+ rsgBindTexture(gPFBackground, 0, texture);
+ float startX = posX, startY = posY;
+ float width = 256, height = 256;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
+ startX, startY + height, 0, 0, 0,
+ startX + width, startY + height, 0, 1, 0,
+ startX + width, startY, 0, 1, 1);
+}
+
+int root(void) {
+
+ rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgClearDepth(1.0f);
+
+ renderOffscreen(true);
+ drawOffscreenResult(0, 0, gOffscreen);
+
+
+ uint32_t w = rsAllocationGetDimX(gOffscreen);
+ uint32_t h = rsAllocationGetDimY(gOffscreen);
+ uint32_t numElements = w*h;
+
+ rsgAllocationSyncAll(gOffscreen, RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET);
+
+ rsAllocationCopy2DRange(gReadBackTest, 0, 0, 0,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, w, h,
+ gOffscreen, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+
+ rsgAllocationSyncAll(gReadBackTest);
+ drawOffscreenResult(0, 300, gReadBackTest);
+
+ rsgBindProgramVertex(gPVBackground);
+ rs_matrix4x4 proj;
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindProgramStore(gPFSBackground);
+ rsgBindTexture(gPFBackground, 0, gTGrid);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ // Position our models on the screen
+ rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom);
+ rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ renderAllMeshes();
+
+ drawDescription();
+
+ return 0;
+}
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 223b1fa..7852197 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -291,6 +291,27 @@ static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
return value.data;
}
+static int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
+ uint32_t attrRes, String8* outError, int32_t defValue = -1)
+{
+ ssize_t idx = indexOfAttribute(tree, attrRes);
+ if (idx < 0) {
+ return defValue;
+ }
+ Res_value value;
+ if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
+ if (value.dataType == Res_value::TYPE_REFERENCE) {
+ resTable->resolveReference(&value, 0);
+ }
+ if (value.dataType < Res_value::TYPE_FIRST_INT
+ || value.dataType > Res_value::TYPE_LAST_INT) {
+ if (outError != NULL) *outError = "attribute is not an integer value";
+ return defValue;
+ }
+ }
+ return value.data;
+}
+
static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
uint32_t attrRes, String8* outError)
{
@@ -320,11 +341,12 @@ static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree&
// These are attribute resource constants for the platform, as found
// in android.R.attr
enum {
+ LABEL_ATTR = 0x01010001,
+ ICON_ATTR = 0x01010002,
NAME_ATTR = 0x01010003,
VERSION_CODE_ATTR = 0x0101021b,
VERSION_NAME_ATTR = 0x0101021c,
- LABEL_ATTR = 0x01010001,
- ICON_ATTR = 0x01010002,
+ SCREEN_ORIENTATION_ATTR = 0x0101001e,
MIN_SDK_VERSION_ATTR = 0x0101020c,
MAX_SDK_VERSION_ATTR = 0x01010271,
REQ_TOUCH_SCREEN_ATTR = 0x01010227,
@@ -634,6 +656,8 @@ int doDump(Bundle* bundle)
bool reqDistinctMultitouchFeature = false;
bool specScreenPortraitFeature = false;
bool specScreenLandscapeFeature = false;
+ bool reqScreenPortraitFeature = false;
+ bool reqScreenLandscapeFeature = false;
// 2.2 also added some other features that apps can request, but that
// have no corresponding permission, so we cannot implement any
// back-compatibility heuristic for them. The below are thus unnecessary
@@ -1022,6 +1046,18 @@ int doDump(Bundle* bundle)
fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
goto bail;
}
+
+ int32_t orien = getResolvedIntegerAttribute(&res, tree,
+ SCREEN_ORIENTATION_ATTR, &error);
+ if (error == "") {
+ if (orien == 0 || orien == 6 || orien == 8) {
+ // Requests landscape, sensorLandscape, or reverseLandscape.
+ reqScreenLandscapeFeature = true;
+ } else if (orien == 1 || orien == 7 || orien == 9) {
+ // Requests portrait, sensorPortrait, or reversePortrait.
+ reqScreenPortraitFeature = true;
+ }
+ }
} else if (tag == "uses-library") {
String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
@@ -1182,12 +1218,16 @@ int doDump(Bundle* bundle)
}
// Landscape/portrait-related compatibility logic
- if (!specScreenLandscapeFeature && !specScreenPortraitFeature && (targetSdk < 13)) {
- // If app has not specified whether it requires portrait or landscape
- // and is targeting an API before Honeycomb MR2, then assume it requires
- // both.
- printf("uses-feature:'android.hardware.screen.portrait'\n");
- printf("uses-feature:'android.hardware.screen.landscape'\n");
+ if (!specScreenLandscapeFeature && !specScreenPortraitFeature) {
+ // If the app has specified any activities in its manifest
+ // that request a specific orientation, then assume that
+ // orientation is required.
+ if (reqScreenLandscapeFeature) {
+ printf("uses-feature:'android.hardware.screen.landscape'\n");
+ }
+ if (reqScreenPortraitFeature) {
+ printf("uses-feature:'android.hardware.screen.portrait'\n");
+ }
}
if (hasMainActivity) {