diff options
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) { |