diff options
Diffstat (limited to 'libs')
59 files changed, 2203 insertions, 1860 deletions
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk index 2f16923de473..b17b3d22044d 100644 --- a/libs/camera/Android.mk +++ b/libs/camera/Android.mk @@ -13,7 +13,6 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libbinder \ libhardware \ - libsurfaceflinger_client \ libui \ libgui diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp index e2883121e497..5eb48da3589e 100644 --- a/libs/camera/Camera.cpp +++ b/libs/camera/Camera.cpp @@ -205,22 +205,6 @@ status_t Camera::startPreview() return c->startPreview(); } -int32_t Camera::getNumberOfVideoBuffers() const -{ - LOGV("getNumberOfVideoBuffers"); - sp <ICamera> c = mCamera; - if (c == 0) return 0; - return c->getNumberOfVideoBuffers(); -} - -sp<IMemory> Camera::getVideoBuffer(int32_t index) const -{ - LOGV("getVideoBuffer: %d", index); - sp <ICamera> c = mCamera; - if (c == 0) return 0; - return c->getVideoBuffer(index); -} - status_t Camera::storeMetaDataInBuffers(bool enabled) { LOGV("storeMetaDataInBuffers: %s", diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp index 931b57d048aa..5f6e5ef4d129 100644 --- a/libs/camera/ICamera.cpp +++ b/libs/camera/ICamera.cpp @@ -46,8 +46,6 @@ enum { STOP_RECORDING, RECORDING_ENABLED, RELEASE_RECORDING_FRAME, - GET_NUM_VIDEO_BUFFERS, - GET_VIDEO_BUFFER, STORE_META_DATA_IN_BUFFERS, }; @@ -149,27 +147,6 @@ public: remote()->transact(RELEASE_RECORDING_FRAME, data, &reply); } - int32_t getNumberOfVideoBuffers() const - { - LOGV("getNumberOfVideoBuffers"); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - remote()->transact(GET_NUM_VIDEO_BUFFERS, data, &reply); - return reply.readInt32(); - } - - sp<IMemory> getVideoBuffer(int32_t index) const - { - LOGV("getVideoBuffer: %d", index); - Parcel data, reply; - data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeInt32(index); - remote()->transact(GET_VIDEO_BUFFER, data, &reply); - sp<IMemory> mem = interface_cast<IMemory>( - reply.readStrongBinder()); - return mem; - } - status_t storeMetaDataInBuffers(bool enabled) { LOGV("storeMetaDataInBuffers: %s", enabled? "true": "false"); @@ -355,19 +332,6 @@ status_t BnCamera::onTransact( releaseRecordingFrame(mem); return NO_ERROR; } break; - case GET_NUM_VIDEO_BUFFERS: { - LOGV("GET_NUM_VIDEO_BUFFERS"); - CHECK_INTERFACE(ICamera, data, reply); - reply->writeInt32(getNumberOfVideoBuffers()); - return NO_ERROR; - } break; - case GET_VIDEO_BUFFER: { - LOGV("GET_VIDEO_BUFFER"); - CHECK_INTERFACE(ICamera, data, reply); - int32_t index = data.readInt32(); - reply->writeStrongBinder(getVideoBuffer(index)->asBinder()); - return NO_ERROR; - } break; case STORE_META_DATA_IN_BUFFERS: { LOGV("STORE_META_DATA_IN_BUFFERS"); CHECK_INTERFACE(ICamera, data, reply); diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index d1a6af1dc11b..58bb0d31f4e2 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -10,7 +10,15 @@ LOCAL_SRC_FILES:= \ SensorEventQueue.cpp \ SensorManager.cpp \ SurfaceTexture.cpp \ - SurfaceTextureClient.cpp + SurfaceTextureClient.cpp \ + ISurfaceComposer.cpp \ + ISurface.cpp \ + ISurfaceComposerClient.cpp \ + IGraphicBufferAlloc.cpp \ + LayerState.cpp \ + SharedBufferStack.cpp \ + Surface.cpp \ + SurfaceComposerClient.cpp \ LOCAL_SHARED_LIBRARIES := \ libcutils \ @@ -21,7 +29,6 @@ LOCAL_SHARED_LIBRARIES := \ libui \ libEGL \ libGLESv2 \ - libsurfaceflinger_client LOCAL_MODULE:= libgui diff --git a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp index e05da725c47f..e05da725c47f 100644 --- a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp +++ b/libs/gui/IGraphicBufferAlloc.cpp diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/gui/ISurface.cpp index 23b90af31143..23b90af31143 100644 --- a/libs/surfaceflinger_client/ISurface.cpp +++ b/libs/gui/ISurface.cpp diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 8951c3f0453a..8951c3f0453a 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 7730eb1fa91b..7730eb1fa91b 100644 --- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index d661fd57914e..bc14ad55149c 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -88,10 +88,11 @@ public: return result; } - virtual status_t queueBuffer(int buf) { + virtual status_t queueBuffer(int buf, int64_t timestamp) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); + data.writeInt64(timestamp); remote()->transact(QUEUE_BUFFER, data, &reply); status_t result = reply.readInt32(); return result; @@ -174,7 +175,8 @@ status_t BnSurfaceTexture::onTransact( case QUEUE_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); - status_t result = queueBuffer(buf); + int64_t timestamp = data.readInt64(); + status_t result = queueBuffer(buf, timestamp); reply->writeInt32(result); return NO_ERROR; } break; @@ -196,7 +198,6 @@ status_t BnSurfaceTexture::onTransact( return NO_ERROR; } break; case SET_TRANSFORM: { - Rect reg; CHECK_INTERFACE(ISurfaceTexture, data, reply); uint32_t transform = data.readInt32(); status_t result = setTransform(transform); diff --git a/libs/surfaceflinger_client/LayerState.cpp b/libs/gui/LayerState.cpp index 01c4c7ebfe84..01c4c7ebfe84 100644 --- a/libs/surfaceflinger_client/LayerState.cpp +++ b/libs/gui/LayerState.cpp diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/gui/SharedBufferStack.cpp index 7505d530e0c5..7505d530e0c5 100644 --- a/libs/surfaceflinger_client/SharedBufferStack.cpp +++ b/libs/gui/SharedBufferStack.cpp diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/gui/Surface.cpp index 21d509a6a8df..0dfbf01aa449 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -753,6 +753,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: res = dispatch_set_buffers_transform( args ); break; + case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: + res = dispatch_set_buffers_timestamp( args ); + break; default: res = NAME_NOT_FOUND; break; @@ -792,6 +795,11 @@ int Surface::dispatch_set_buffers_transform(va_list args) { return setBuffersTransform(transform); } +int Surface::dispatch_set_buffers_timestamp(va_list args) { + int64_t timestamp = va_arg(args, int64_t); + return setBuffersTimestamp(timestamp); +} + void Surface::setUsage(uint32_t reqUsage) { Mutex::Autolock _l(mSurfaceLock); @@ -910,6 +918,13 @@ int Surface::setBuffersTransform(int transform) return NO_ERROR; } +int Surface::setBuffersTimestamp(int64_t timestamp) +{ + // Surface doesn't really have anything meaningful to do with timestamps + // so they'll just be dropped here. + return NO_ERROR; +} + // ---------------------------------------------------------------------------- int Surface::getConnectedApi() const diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index d3367246a119..d3367246a119 100644 --- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 5c6d71b1501b..cdaca47b6564 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -76,9 +76,15 @@ static float mtxRot270[16] = { static void mtxMul(float out[16], const float a[16], const float b[16]); SurfaceTexture::SurfaceTexture(GLuint tex) : - mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT), - mCurrentTransform(0), mLastQueued(INVALID_BUFFER_SLOT), - mLastQueuedTransform(0), mNextTransform(0), mTexName(tex) { + mBufferCount(MIN_BUFFER_SLOTS), + mCurrentTexture(INVALID_BUFFER_SLOT), + mCurrentTransform(0), + mCurrentTimestamp(0), + mLastQueued(INVALID_BUFFER_SLOT), + mLastQueuedTransform(0), + mLastQueuedTimestamp(0), + mNextTransform(0), + mTexName(tex) { LOGV("SurfaceTexture::SurfaceTexture"); for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; @@ -153,7 +159,7 @@ status_t SurfaceTexture::dequeueBuffer(int *buf) { return OK; } -status_t SurfaceTexture::queueBuffer(int buf) { +status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { LOGV("SurfaceTexture::queueBuffer"); Mutex::Autolock lock(mMutex); if (buf < 0 || mBufferCount <= buf) { @@ -172,6 +178,7 @@ status_t SurfaceTexture::queueBuffer(int buf) { mLastQueued = buf; mLastQueuedCrop = mNextCrop; mLastQueuedTransform = mNextTransform; + mLastQueuedTimestamp = timestamp; if (mFrameAvailableListener != 0) { mFrameAvailableListener->onFrameAvailable(); } @@ -246,12 +253,13 @@ status_t SurfaceTexture::updateTexImage() { mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer; mCurrentCrop = mLastQueuedCrop; mCurrentTransform = mLastQueuedTransform; + mCurrentTimestamp = mLastQueuedTimestamp; } return OK; } void SurfaceTexture::getTransformMatrix(float mtx[16]) { - LOGV("SurfaceTexture::updateTexImage"); + LOGV("SurfaceTexture::getTransformMatrix"); Mutex::Autolock lock(mMutex); float xform[16]; @@ -342,6 +350,12 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) { mtxMul(mtx, mtxFlipV, mtxBeforeFlipV); } +nsecs_t SurfaceTexture::getTimestamp() { + LOGV("SurfaceTexture::getTimestamp"); + Mutex::Autolock lock(mMutex); + return mCurrentTimestamp; +} + void SurfaceTexture::setFrameAvailableListener( const sp<FrameAvailableListener>& l) { LOGV("SurfaceTexture::setFrameAvailableListener"); diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 7f1d9cbf22c5..a4812d073546 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -26,7 +26,8 @@ namespace android { SurfaceTextureClient::SurfaceTextureClient( const sp<ISurfaceTexture>& surfaceTexture): mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1), - mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() { + mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), + mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mMutex() { // Initialize the ANativeWindow function pointers. ANativeWindow::setSwapInterval = setSwapInterval; ANativeWindow::dequeueBuffer = dequeueBuffer; @@ -135,9 +136,17 @@ int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) { int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { LOGV("SurfaceTextureClient::queueBuffer"); Mutex::Autolock lock(mMutex); + int64_t timestamp; + if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) { + timestamp = systemTime(SYSTEM_TIME_MONOTONIC); + LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms", + timestamp / 1000000.f); + } else { + timestamp = mTimestamp; + } for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { if (mSlots[i]->handle == buffer->handle) { - return mSurfaceTexture->queueBuffer(i); + return mSurfaceTexture->queueBuffer(i, timestamp); } } LOGE("queueBuffer: unknown buffer queued"); @@ -196,6 +205,9 @@ int SurfaceTextureClient::perform(int operation, va_list args) case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: res = dispatchSetBuffersTransform(args); break; + case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: + res = dispatchSetBuffersTimestamp(args); + break; default: res = NAME_NOT_FOUND; break; @@ -240,6 +252,11 @@ int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) { return setBuffersTransform(transform); } +int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) { + int64_t timestamp = va_arg(args, int64_t); + return setBuffersTimestamp(timestamp); +} + int SurfaceTextureClient::connect(int api) { LOGV("SurfaceTextureClient::connect"); // XXX: Implement this! @@ -323,6 +340,14 @@ int SurfaceTextureClient::setBuffersTransform(int transform) return err; } +int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp) +{ + LOGV("SurfaceTextureClient::setBuffersTimestamp"); + Mutex::Autolock lock(mMutex); + mTimestamp = timestamp; + return NO_ERROR; +} + void SurfaceTextureClient::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { mSlots[i] = 0; diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk index 7516299446ab..ecd09951153e 100644 --- a/libs/gui/tests/Android.mk +++ b/libs/gui/tests/Android.mk @@ -9,6 +9,7 @@ LOCAL_MODULE := SurfaceTexture_test LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ + Surface_test.cpp \ SurfaceTextureClient_test.cpp \ SurfaceTexture_test.cpp \ @@ -20,7 +21,6 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libgui \ libstlport \ - libsurfaceflinger_client \ libui \ libutils \ diff --git a/libs/surfaceflinger_client/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index fd07479a0587..fd07479a0587 100644 --- a/libs/surfaceflinger_client/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index f4a0161b2e1f..b465fee71a0a 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -42,7 +42,6 @@ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui LOCAL_MODULE := libhwui LOCAL_MODULE_TAGS := optional - LOCAL_PRELINK_MODULE := false include $(BUILD_SHARED_LIBRARY) diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h index 14471bc7b717..f74238e9e426 100644 --- a/libs/hwui/Debug.h +++ b/libs/hwui/Debug.h @@ -26,7 +26,7 @@ // Turn on to enable memory usage summary on each frame #define DEBUG_MEMORY_USAGE 0 -// Turn on to enable layers debugging when renderered as regions +// Turn on to enable layers debugging when rendered as regions #define DEBUG_LAYERS_AS_REGIONS 0 // Turn on to display debug info about vertex/fragment shaders @@ -35,7 +35,7 @@ // Turn on to display info about layers #define DEBUG_LAYERS 0 -// Turn on to display debug infor about 9patch objects +// Turn on to display debug info about 9patch objects #define DEBUG_PATCHES 0 // Turn on to display vertex and tex coords data about 9patch objects // This flag requires DEBUG_PATCHES to be turned on diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 868290bf0f8b..c7459d151816 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -53,6 +53,7 @@ const char* DisplayList::OP_NAMES[] = { "DrawArc", "DrawPath", "DrawLines", + "DrawPoints", "DrawText", "ResetShader", "SetupShader", @@ -92,13 +93,11 @@ void DisplayList::clearResources() { mPaints.clear(); for (size_t i = 0; i < mPaths.size(); i++) { - delete mPaths.itemAt(i); + SkPath* path = mPaths.itemAt(i); + caches.pathCache.remove(path); + delete path; } mPaths.clear(); - for (size_t i = 0; i < mOriginalPaths.size(); i++) { - caches.resourceCache.decrementRefcount(mOriginalPaths.itemAt(i)); - } - mOriginalPaths.clear(); for (size_t i = 0; i < mMatrices.size(); i++) { delete mMatrices.itemAt(i); @@ -150,13 +149,6 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde mPaths.add(paths.itemAt(i)); } - const Vector<SkPath*> &originalPaths = recorder.getOriginalPaths(); - for (size_t i = 0; i < originalPaths.size(); i++) { - SkPath* path = originalPaths.itemAt(i); - mOriginalPaths.add(path); - caches.resourceCache.incrementRefcount(path); - } - const Vector<SkMatrix*> &matrices = recorder.getMatrices(); for (size_t i = 0; i < matrices.size(); i++) { mMatrices.add(matrices.itemAt(i)); @@ -452,6 +444,13 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) renderer.drawLines(points, count, getPaint()); } break; + case DrawPoints: { + int count = 0; + float* points = getFloats(count); + DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); + renderer.drawPoints(points, count, getPaint()); + } + break; case DrawText: { getText(&text); int count = getInt(); @@ -533,12 +532,6 @@ void DisplayListRenderer::reset() { } mBitmapResources.clear(); - for (size_t i = 0; i < mOriginalPaths.size(); i++) { - SkPath* resource = mOriginalPaths.itemAt(i); - caches.resourceCache.decrementRefcount(resource); - } - mOriginalPaths.clear(); - for (size_t i = 0; i < mShaders.size(); i++) { caches.resourceCache.decrementRefcount(mShaders.itemAt(i)); } @@ -804,6 +797,12 @@ void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) { addPaint(paint); } +void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) { + addOp(DisplayList::DrawPoints); + addFloats(points, count); + addPaint(paint); +} + void DisplayListRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint) { addOp(DisplayList::DrawText); diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 6fc315c0c1d6..da57e4a59ed2 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -89,6 +89,7 @@ public: DrawArc, DrawPath, DrawLines, + DrawPoints, DrawText, ResetShader, SetupShader, @@ -193,7 +194,6 @@ private: Vector<SkPaint*> mPaints; Vector<SkPath*> mPaths; - Vector<SkPath*> mOriginalPaths; Vector<SkMatrix*> mMatrices; Vector<SkiaShader*> mShaders; @@ -265,6 +265,7 @@ public: float startAngle, float sweepAngle, bool useCenter, SkPaint* paint); void drawPath(SkPath* path, SkPaint* paint); void drawLines(float* points, int count, SkPaint* paint); + void drawPoints(float* points, int count, SkPaint* paint); void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint); void resetShader(); @@ -298,10 +299,6 @@ public: return mPaths; } - const Vector<SkPath*>& getOriginalPaths() const { - return mOriginalPaths; - } - const Vector<SkMatrix*>& getMatrices() const { return mMatrices; } @@ -383,16 +380,9 @@ private: SkPath* pathCopy = mPathMap.valueFor(path); if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) { - if (pathCopy == NULL) { - pathCopy = path; - mOriginalPaths.add(path); - Caches& caches = Caches::getInstance(); - caches.resourceCache.incrementRefcount(path); - } else { - pathCopy = new SkPath(*path); - mPaths.add(pathCopy); - } + pathCopy = new SkPath(*path); mPathMap.add(path, pathCopy); + mPaths.add(pathCopy); } addInt((int) pathCopy); @@ -469,7 +459,6 @@ private: Vector<SkPaint*> mPaints; DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap; - Vector<SkPath*> mOriginalPaths; Vector<SkPath*> mPaths; DefaultKeyedVector<SkPath*, SkPath*> mPathMap; diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index bb2843790ed7..26e240f2be99 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -103,6 +103,11 @@ struct Layer { * have been drawn. */ Region region; + /** + * If the region is a rectangle, coordinates of the + * region are stored here. + */ + Rect regionRect; /** * Color filter used to draw this layer. Optional. diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index f92e20b841f9..ba110ec0efae 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -92,11 +92,7 @@ Region* LayerRenderer::getRegion() { void LayerRenderer::generateMesh() { #if RENDER_LAYERS_AS_REGIONS -#if RENDER_LAYERS_RECT_AS_RECT if (mLayer->region.isRect() || mLayer->region.isEmpty()) { -#else - if (mLayer->region.isEmpty()) { -#endif if (mLayer->mesh) { delete mLayer->mesh; delete mLayer->meshIndices; @@ -105,6 +101,20 @@ void LayerRenderer::generateMesh() { mLayer->meshIndices = NULL; mLayer->meshElementCount = 0; } + + const android::Rect& bounds = mLayer->region.getBounds(); + mLayer->regionRect.set(bounds.leftTop().x, bounds.leftTop().y, + bounds.rightBottom().x, bounds.rightBottom().y); + + const float texX = 1.0f / float(mLayer->width); + const float texY = 1.0f / float(mLayer->height); + const float height = mLayer->layer.getHeight(); + mLayer->texCoords.set( + mLayer->regionRect.left * texX, + (height - mLayer->regionRect.top) * texY, + mLayer->regionRect.right * texX, + (height - mLayer->regionRect.bottom) * texY); + return; } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index d9d7d231a38f..6fabbef39451 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -646,13 +646,14 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { #if RENDER_LAYERS_AS_REGIONS -#if RENDER_LAYERS_RECT_AS_RECT if (layer->region.isRect()) { - composeLayerRect(layer, rect); + const android::Rect& bounds = layer->region.getBounds(); + layer->regionRect.set(bounds.leftTop().x, bounds.leftTop().y, + bounds.rightBottom().x, bounds.rightBottom().y); + composeLayerRect(layer, layer->regionRect); layer->region.clear(); return; } -#endif if (!layer->region.isEmpty()) { size_t count; @@ -881,6 +882,11 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { mDescription.hasAlpha8Texture = isAlpha8; } +void OpenGLRenderer::setupDrawPoint(float pointSize) { + mDescription.isPoint = true; + mDescription.pointSize = pointSize; +} + void OpenGLRenderer::setupDrawColor(int color) { setupDrawColor(color, (color >> 24) & 0xFF); } @@ -989,6 +995,11 @@ void OpenGLRenderer::setupDrawModelView(float left, float top, float right, floa } } +void OpenGLRenderer::setupDrawPointUniforms() { + int slot = mCaches.currentProgram->getUniform("pointSize"); + glUniform1f(slot, mDescription.pointSize); +} + void OpenGLRenderer::setupDrawColorUniforms() { if (mColorSet || (mShader && mSetShaderColor)) { mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA); @@ -1072,6 +1083,44 @@ bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, u return false; } +void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint) { + int alpha; + SkXfermode::Mode mode; + getAlphaAndMode(paint, &alpha, &mode); + + setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + + float x = left; + float y = top; + + bool ignoreTransform = false; + if (mSnapshot->transform->isPureTranslate()) { + x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f); + y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f); + ignoreTransform = true; + } + + setupDraw(); + setupDrawWithTexture(true); + if (paint) { + setupDrawAlpha8Color(paint->getColor(), alpha); + } + setupDrawColorFilter(); + setupDrawShader(); + setupDrawBlending(true, mode); + setupDrawProgram(); + setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform); + setupDrawTexture(texture->id); + setupDrawPureColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawShaderUniforms(); + setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); + + finishDrawTexture(); +} + void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) { const float right = left + bitmap->width(); const float bottom = top + bitmap->height(); @@ -1085,7 +1134,11 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint if (!texture) return; const AutoTexture autoCleanup(texture); - drawTextureRect(left, top, right, bottom, texture, paint); + if (bitmap->getConfig() == SkBitmap::kA8_Config) { + drawAlphaBitmap(texture, left, top, paint); + } else { + drawTextureRect(left, top, right, bottom, texture, paint); + } } void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) { @@ -1388,26 +1441,66 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { } else { // TODO: Handle the AA case for (int i = 0; i < count; i += 4) { - const float left = fmin(points[i], points[i + 1]); - const float right = fmax(points[i], points[i + 1]); - const float top = fmin(points[i + 2], points[i + 3]); - const float bottom = fmax(points[i + 2], points[i + 3]); + TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f); + TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f); - if (!quickReject(left, top, right, bottom)) { - TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f); - TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f); + generatedVerticesCount += 2; - generatedVerticesCount += 2; + const float left = fmin(points[i], points[i + 2]); + const float right = fmax(points[i], points[i + 2]); + const float top = fmin(points[i + 1], points[i + 3]); + const float bottom = fmax(points[i + 1], points[i + 3]); - dirtyLayer(left, top, right, bottom, *mSnapshot->transform); - } + dirtyLayer(left, top, + right == left ? left + 1 : right, bottom == top ? top + 1 : bottom, + *mSnapshot->transform); } - if (generatedVerticesCount > 0) { - glLineWidth(1.0f); - glDrawArrays(GL_LINES, 0, generatedVerticesCount); - } + glLineWidth(1.0f); + glDrawArrays(GL_LINES, 0, generatedVerticesCount); + } +} + +void OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) { + if (mSnapshot->isIgnored()) return; + + // TODO: The paint's cap style defines whether the points are square or circular + // TODO: Handle AA for round points + + // A stroke width of 0 has a special meaningin Skia: + // it draws an unscaled 1px point + const bool isHairLine = paint->getStrokeWidth() == 0.0f; + + int alpha; + SkXfermode::Mode mode; + getAlphaAndMode(paint, &alpha, &mode); + + int verticesCount = count >> 1; + int generatedVerticesCount = 0; + + TextureVertex pointsData[verticesCount]; + TextureVertex* vertex = &pointsData[0]; + + setupDraw(); + setupDrawPoint(isHairLine ? 1.0f : paint->getStrokeWidth()); + setupDrawColor(paint->getColor(), alpha); + setupDrawColorFilter(); + setupDrawShader(); + setupDrawBlending(mode); + setupDrawProgram(); + setupDrawModelViewIdentity(); + setupDrawColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawPointUniforms(); + setupDrawShaderIdentityUniforms(); + setupDrawMesh(vertex); + + for (int i = 0; i < count; i += 2) { + TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f); + generatedVerticesCount++; } + + glDrawArrays(GL_POINTS, 0, generatedVerticesCount); } void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { @@ -1658,14 +1751,9 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { #if RENDER_LAYERS_AS_REGIONS if (!layer->region.isEmpty()) { -#if RENDER_LAYERS_RECT_AS_RECT if (layer->region.isRect()) { - const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight()); - composeLayerRect(layer, r); + composeLayerRect(layer, layer->regionRect); } else if (layer->mesh) { -#else - if (layer->mesh) { -#endif const float a = alpha / 255.0f; const Rect& rect = layer->layer; @@ -1675,13 +1763,11 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { setupDrawColorFilter(); setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false); setupDrawProgram(); + setupDrawModelViewTranslate(x, y, + x + layer->layer.getWidth(), y + layer->layer.getHeight()); setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); setupDrawTexture(layer->texture); - // TODO: The current layer, if any, will be dirtied with the bounding box - // of the layer we are drawing. Since the layer we are drawing has - // a mesh, we know the dirty region, we should use it instead - setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom); setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]); glDrawElements(GL_TRIANGLES, layer->meshElementCount, diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 73624733df0a..4b93b8036cbb 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -119,6 +119,7 @@ public: float startAngle, float sweepAngle, bool useCenter, SkPaint* paint); virtual void drawPath(SkPath* path, SkPaint* paint); virtual void drawLines(float* points, int count, SkPaint* paint); + virtual void drawPoints(float* points, int count, SkPaint* paint); virtual void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint); @@ -279,6 +280,8 @@ private: void drawShape(float left, float top, const PathTexture* texture, SkPaint* paint); void drawRectAsShape(float left, float top, float right, float bottom, SkPaint* p); + void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint); + /** * Draws a textured rectangle with the specified texture. The specified coordinates * are transformed by the current snapshot's transform matrix. @@ -422,6 +425,7 @@ private: * Various methods to setup OpenGL rendering. */ void setupDrawWithTexture(bool isAlpha8 = false); + void setupDrawPoint(float pointSize); void setupDrawColor(int color); void setupDrawColor(int color, int alpha); void setupDrawColor(float r, float g, float b, float a); @@ -440,6 +444,7 @@ private: bool ignoreTransform = false, bool ignoreModelView = false); void setupDrawModelViewTranslate(float left, float top, float right, float bottom, bool ignoreTransform = false); + void setupDrawPointUniforms(); void setupDrawColorUniforms(); void setupDrawPureColorUniforms(); void setupDrawShaderIdentityUniforms(); diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index dc67e160fabf..7ff8b74810dd 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -41,8 +41,7 @@ struct PathCacheEntry: public ShapeCacheEntry { path = NULL; } - PathCacheEntry(const PathCacheEntry& entry): - ShapeCacheEntry(entry) { + PathCacheEntry(const PathCacheEntry& entry): ShapeCacheEntry(entry) { path = entry.path; } @@ -55,6 +54,7 @@ struct PathCacheEntry: public ShapeCacheEntry { } SkPath* path; + }; // PathCacheEntry /** diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 0b6c7b5c64d2..f0bc36bf447f 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -41,6 +41,8 @@ const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n"; const char* gVS_Header_Uniforms = "uniform mat4 transform;\n"; +const char* gVS_Header_Uniforms_IsPoint = + "uniform mediump float pointSize;\n"; const char* gVS_Header_Uniforms_HasGradient[3] = { // Linear "uniform mat4 screenSpace;\n", @@ -51,11 +53,13 @@ const char* gVS_Header_Uniforms_HasGradient[3] = { }; const char* gVS_Header_Uniforms_HasBitmap = "uniform mat4 textureTransform;\n" - "uniform vec2 textureDimension;\n"; + "uniform mediump vec2 textureDimension;\n"; const char* gVS_Header_Varyings_HasTexture = "varying vec2 outTexCoords;\n"; const char* gVS_Header_Varyings_HasBitmap = "varying vec2 outBitmapTexCoords;\n"; +const char* gVS_Header_Varyings_PointHasBitmap = + "varying vec2 outPointBitmapTexCoords;\n"; const char* gVS_Header_Varyings_HasGradient[3] = { // Linear "varying vec2 linear;\n", @@ -78,8 +82,12 @@ const char* gVS_Main_OutGradient[3] = { }; const char* gVS_Main_OutBitmapTexCoords = " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; +const char* gVS_Main_OutPointBitmapTexCoords = + " outPointBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; const char* gVS_Main_Position = " gl_Position = transform * position;\n"; +const char* gVS_Main_PointSize = + " gl_PointSize = pointSize;\n"; const char* gVS_Footer = "}\n\n"; @@ -93,6 +101,9 @@ const char* gFS_Header = "precision mediump float;\n\n"; const char* gFS_Uniforms_Color = "uniform vec4 color;\n"; +const char* gFS_Header_Uniforms_PointHasBitmap = + "uniform vec2 textureDimension;\n" + "uniform float pointSize;\n"; const char* gFS_Uniforms_TextureSampler = "uniform sampler2D sampler;\n"; const char* gFS_Uniforms_GradientSampler[3] = { @@ -121,6 +132,10 @@ const char* gFS_Main = "\nvoid main(void) {\n" " lowp vec4 fragColor;\n"; +const char* gFS_Main_PointBitmapTexCoords = + " vec2 outBitmapTexCoords = outPointBitmapTexCoords + " + "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n"; + // Fast cases const char* gFS_Fast_SingleColor = "\nvoid main(void) {\n" @@ -347,6 +362,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasBitmap) { shader.append(gVS_Header_Uniforms_HasBitmap); } + if (description.isPoint) { + shader.append(gVS_Header_Uniforms_IsPoint); + } // Varyings if (description.hasTexture) { shader.append(gVS_Header_Varyings_HasTexture); @@ -355,7 +373,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { - shader.append(gVS_Header_Varyings_HasBitmap); + shader.append(description.isPoint ? + gVS_Header_Varyings_PointHasBitmap : + gVS_Header_Varyings_HasBitmap); } // Begin the shader @@ -367,7 +387,12 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Main_OutGradient[description.gradientType]); } if (description.hasBitmap) { - shader.append(gVS_Main_OutBitmapTexCoords); + shader.append(description.isPoint ? + gVS_Main_OutPointBitmapTexCoords : + gVS_Main_OutBitmapTexCoords); + } + if (description.isPoint) { + shader.append(gVS_Main_PointSize); } // Output transformed position shader.append(gVS_Main_Position); @@ -399,7 +424,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { - shader.append(gVS_Header_Varyings_HasBitmap); + shader.append(description.isPoint ? + gVS_Header_Varyings_PointHasBitmap : + gVS_Header_Varyings_HasBitmap); } // Uniforms @@ -417,9 +444,13 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasGradient) { shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); } + if (description.hasBitmap && description.isPoint) { + shader.append(gFS_Header_Uniforms_PointHasBitmap); + } // Optimization for common cases - if (!blendFramebuffer && description.colorOp == ProgramDescription::kColorNone) { + if (!blendFramebuffer && description.colorOp == ProgramDescription::kColorNone && + !description.isPoint) { bool fast = false; const bool noShader = !description.hasGradient && !description.hasBitmap; @@ -507,6 +538,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gFS_Main_FetchGradient[description.gradientType]); } if (description.hasBitmap) { + if (description.isPoint) { + shader.append(gFS_Main_PointBitmapTexCoords); + } if (!description.isBitmapNpot) { shader.append(gFS_Main_FetchBitmap); } else { diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index ead5b920c1dc..737d91ba12f9 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -71,7 +71,9 @@ namespace uirenderer { #define PROGRAM_BITMAP_WRAPT_SHIFT 11 #define PROGRAM_GRADIENT_TYPE_SHIFT 33 -#define PROGRAM_MODULATE 35 +#define PROGRAM_MODULATE_SHIFT 35 + +#define PROGRAM_IS_POINT_SHIFT 36 /////////////////////////////////////////////////////////////////////////////// // Types @@ -135,6 +137,9 @@ struct ProgramDescription { SkXfermode::Mode framebufferMode; bool swapSrcDst; + bool isPoint; + float pointSize; + /** * Resets this description. All fields are reset back to the default * values they hold after building a new instance. @@ -162,6 +167,9 @@ struct ProgramDescription { framebufferMode = SkXfermode::kClear_Mode; swapSrcDst = false; + + isPoint = false; + pointSize = 0.0f; } /** @@ -223,7 +231,8 @@ struct ProgramDescription { } key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT; if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST; - if (modulate) key |= programid(0x1) << PROGRAM_MODULATE; + if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT; + if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT; return key; } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 1aef99b53f68..2d8b6f3950f6 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -27,8 +27,6 @@ // If turned on, layers drawn inside FBOs are optimized with regions #define RENDER_LAYERS_AS_REGIONS 1 -// If turned on, layers that map to a single rect are drawn as a rect -#define RENDER_LAYERS_RECT_AS_RECT 0 /** * Debug level for app developers. diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h index 4c626dd49303..b5cc29c9a691 100644 --- a/libs/hwui/ShapeCache.h +++ b/libs/hwui/ShapeCache.h @@ -89,14 +89,17 @@ struct ShapeCacheEntry { join = SkPaint::kDefault_Join; cap = SkPaint::kDefault_Cap; style = SkPaint::kFill_Style; - miter = 4.0f; - strokeWidth = 1.0f; + float v = 4.0f; + miter = *(uint32_t*) &v; + v = 1.0f; + strokeWidth = *(uint32_t*) &v; + pathEffect = NULL; } ShapeCacheEntry(const ShapeCacheEntry& entry): shapeType(entry.shapeType), join(entry.join), cap(entry.cap), style(entry.style), miter(entry.miter), - strokeWidth(entry.strokeWidth) { + strokeWidth(entry.strokeWidth), pathEffect(entry.pathEffect) { } ShapeCacheEntry(ShapeType type, SkPaint* paint) { @@ -108,18 +111,19 @@ struct ShapeCacheEntry { v = paint->getStrokeWidth(); strokeWidth = *(uint32_t*) &v; style = paint->getStyle(); + pathEffect = paint->getPathEffect(); } virtual ~ShapeCacheEntry() { } - // shapeType must be checked in subclasses operator< ShapeType shapeType; SkPaint::Join join; SkPaint::Cap cap; SkPaint::Style style; uint32_t miter; uint32_t strokeWidth; + SkPathEffect* pathEffect; bool operator<(const ShapeCacheEntry& rhs) const { LTE_INT(shapeType) { @@ -128,7 +132,9 @@ struct ShapeCacheEntry { LTE_INT(style) { LTE_INT(miter) { LTE_INT(strokeWidth) { - return lessThan(rhs); + LTE_INT(pathEffect) { + return lessThan(rhs); + } } } } diff --git a/libs/hwui/utils/GenerationCache.h b/libs/hwui/utils/GenerationCache.h deleted file mode 100644 index 42e6d9bb8cda..000000000000 --- a/libs/hwui/utils/GenerationCache.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2010 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 ANDROID_HWUI_GENERATION_CACHE_H -#define ANDROID_HWUI_GENERATION_CACHE_H - -#include <utils/KeyedVector.h> -#include <utils/RefBase.h> - -namespace android { -namespace uirenderer { - -template<typename EntryKey, typename EntryValue> -class OnEntryRemoved { -public: - virtual ~OnEntryRemoved() { }; - virtual void operator()(EntryKey& key, EntryValue& value) = 0; -}; // class OnEntryRemoved - -template<typename EntryKey, typename EntryValue> -struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > { - Entry() { } - Entry(const Entry<EntryKey, EntryValue>& e): - key(e.key), value(e.value), parent(e.parent), child(e.child) { } - Entry(sp<Entry<EntryKey, EntryValue> > e): - key(e->key), value(e->value), parent(e->parent), child(e->child) { } - - EntryKey key; - EntryValue value; - - sp<Entry<EntryKey, EntryValue> > parent; - sp<Entry<EntryKey, EntryValue> > child; -}; // struct Entry - -template<typename K, typename V> -class GenerationCache { -public: - GenerationCache(uint32_t maxCapacity); - virtual ~GenerationCache(); - - enum Capacity { - kUnlimitedCapacity, - }; - - void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener); - - void clear(); - - bool contains(K key) const; - V get(K key); - K getKeyAt(uint32_t index) const; - bool put(K key, V value); - V remove(K key); - V removeOldest(); - V getValueAt(uint32_t index) const; - - uint32_t size() const; - - void addToCache(sp<Entry<K, V> > entry, K key, V value); - void attachToCache(sp<Entry<K, V> > entry); - void detachFromCache(sp<Entry<K, V> > entry); - - V removeAt(ssize_t index); - - KeyedVector<K, sp<Entry<K, V> > > mCache; - uint32_t mMaxCapacity; - - OnEntryRemoved<K, V>* mListener; - - sp<Entry<K, V> > mOldest; - sp<Entry<K, V> > mYoungest; -}; // class GenerationCache - -template<typename K, typename V> -GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { -}; - -template<typename K, typename V> -GenerationCache<K, V>::~GenerationCache() { - clear(); -}; - -template<typename K, typename V> -uint32_t GenerationCache<K, V>::size() const { - return mCache.size(); -} - -template<typename K, typename V> -void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) { - mListener = listener; -} - -template<typename K, typename V> -void GenerationCache<K, V>::clear() { - if (mListener) { - for (uint32_t i = 0; i < mCache.size(); i++) { - sp<Entry<K, V> > entry = mCache.valueAt(i); - if (mListener) { - (*mListener)(entry->key, entry->value); - } - } - } - mCache.clear(); - mYoungest.clear(); - mOldest.clear(); -} - -template<typename K, typename V> -bool GenerationCache<K, V>::contains(K key) const { - return mCache.indexOfKey(key) >= 0; -} - -template<typename K, typename V> -K GenerationCache<K, V>::getKeyAt(uint32_t index) const { - return mCache.keyAt(index); -} - -template<typename K, typename V> -V GenerationCache<K, V>::getValueAt(uint32_t index) const { - return mCache.valueAt(index)->value; -} - -template<typename K, typename V> -V GenerationCache<K, V>::get(K key) { - ssize_t index = mCache.indexOfKey(key); - if (index >= 0) { - sp<Entry<K, V> > entry = mCache.valueAt(index); - if (entry.get()) { - detachFromCache(entry); - attachToCache(entry); - return entry->value; - } - } - - return NULL; -} - -template<typename K, typename V> -bool GenerationCache<K, V>::put(K key, V value) { - if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) { - removeOldest(); - } - - ssize_t index = mCache.indexOfKey(key); - if (index < 0) { - sp<Entry<K, V> > entry = new Entry<K, V>; - addToCache(entry, key, value); - return true; - } - - return false; -} - -template<typename K, typename V> -void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) { - entry->key = key; - entry->value = value; - mCache.add(key, entry); - attachToCache(entry); -} - -template<typename K, typename V> -V GenerationCache<K, V>::remove(K key) { - ssize_t index = mCache.indexOfKey(key); - if (index >= 0) { - return removeAt(index); - } - - return NULL; -} - -template<typename K, typename V> -V GenerationCache<K, V>::removeAt(ssize_t index) { - sp<Entry<K, V> > entry = mCache.valueAt(index); - if (mListener) { - (*mListener)(entry->key, entry->value); - } - mCache.removeItemsAt(index, 1); - detachFromCache(entry); - - return entry->value; -} - -template<typename K, typename V> -V GenerationCache<K, V>::removeOldest() { - if (mOldest.get()) { - ssize_t index = mCache.indexOfKey(mOldest->key); - if (index >= 0) { - return removeAt(index); - } - } - - return NULL; -} - -template<typename K, typename V> -void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) { - if (!mYoungest.get()) { - mYoungest = mOldest = entry; - } else { - entry->parent = mYoungest; - mYoungest->child = entry; - mYoungest = entry; - } -} - -template<typename K, typename V> -void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) { - if (entry->parent.get()) { - entry->parent->child = entry->child; - } - - if (entry->child.get()) { - entry->child->parent = entry->parent; - } - - if (mOldest == entry) { - mOldest = entry->child; - } - - if (mYoungest == entry) { - mYoungest = entry->parent; - } - - entry->parent.clear(); - entry->child.clear(); -} - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_GENERATION_CACHE_H diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk index 083688771dac..14152d865946 100644 --- a/libs/rs/Android.mk +++ b/libs/rs/Android.mk @@ -28,7 +28,6 @@ RSG_GENERATOR:=$(LOCAL_BUILT_MODULE) # slangdata_output_var_name := rs_runtime_lib_bc # LOCAL_MODULE := librslib_rt -# LOCAL_PRELINK_MODULE := false # LOCAL_MODULE_CLASS := STATIC_LIBRARIES # LOCAL_MODULE_TAGS := optional @@ -114,7 +113,9 @@ LOCAL_SRC_FILES:= \ rsStream.cpp \ rsThreadIO.cpp \ rsType.cpp \ - rsVertexArray.cpp + rsVertexArray.cpp \ + driver/rsdBcc.cpp \ + driver/rsdCore.cpp LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index ffa9a8c8b74b..cb6d7e05ebdb 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -24,52 +24,7 @@ extern "C" { #endif -////////////////////////////////////////////////////// -// - -typedef void * RsAsyncVoidPtr; - -typedef void * RsAdapter1D; -typedef void * RsAdapter2D; -typedef void * RsAllocation; -typedef void * RsAnimation; -typedef void * RsContext; -typedef void * RsDevice; -typedef void * RsElement; -typedef void * RsFile; -typedef void * RsFont; -typedef void * RsSampler; -typedef void * RsScript; -typedef void * RsMesh; -typedef void * RsType; -typedef void * RsObjectBase; - -typedef void * RsProgram; -typedef void * RsProgramVertex; -typedef void * RsProgramFragment; -typedef void * RsProgramStore; -typedef void * RsProgramRaster; - -typedef void (* RsBitmapCallback_t)(void *); - -enum RsDeviceParam { - RS_DEVICE_PARAM_FORCE_SOFTWARE_GL, - RS_DEVICE_PARAM_COUNT -}; - -typedef struct { - uint32_t colorMin; - uint32_t colorPref; - uint32_t alphaMin; - uint32_t alphaPref; - uint32_t depthMin; - uint32_t depthPref; - uint32_t stencilMin; - uint32_t stencilPref; - uint32_t samplesMin; - uint32_t samplesPref; - float samplesQ; -} RsSurfaceConfig; +#include "RenderScriptDefines.h" RsDevice rsDeviceCreate(); void rsDeviceDestroy(RsDevice); @@ -80,258 +35,12 @@ RsContext rsContextCreateGL(RsDevice, uint32_t version, RsSurfaceConfig sc, uint32_t dpi); void rsContextDestroy(RsContext); -enum RsMessageToClientType { - RS_MESSAGE_TO_CLIENT_NONE = 0, - RS_MESSAGE_TO_CLIENT_EXCEPTION = 1, - RS_MESSAGE_TO_CLIENT_RESIZE = 2, - RS_MESSAGE_TO_CLIENT_ERROR = 3, - RS_MESSAGE_TO_CLIENT_USER = 4 -}; - RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait); RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait); void rsContextInitToClient(RsContext); void rsContextDeinitToClient(RsContext); -#define RS_MAX_TEXTURE 2 -#define RS_MAX_ATTRIBS 16 - - -enum RsAllocationUsageType { - RS_ALLOCATION_USAGE_SCRIPT = 0x0001, - RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE = 0x0002, - RS_ALLOCATION_USAGE_GRAPHICS_VERTEX = 0x0004, - RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS = 0x0008, - - RS_ALLOCATION_USAGE_ALL = 0x000F -}; - -enum RsAllocationMipmapControl { - RS_ALLOCATION_MIPMAP_NONE = 0, - RS_ALLOCATION_MIPMAP_FULL = 1, - RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE = 2 -}; - -enum RsAllocationCubemapFace { - RS_ALLOCATION_CUBMAP_FACE_POSITVE_X = 0, - RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_X = 1, - RS_ALLOCATION_CUBMAP_FACE_POSITVE_Y = 2, - RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Y = 3, - RS_ALLOCATION_CUBMAP_FACE_POSITVE_Z = 4, - RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Z = 5 -}; - -enum RsDataType { - RS_TYPE_NONE, - RS_TYPE_FLOAT_16, - RS_TYPE_FLOAT_32, - RS_TYPE_FLOAT_64, - RS_TYPE_SIGNED_8, - RS_TYPE_SIGNED_16, - RS_TYPE_SIGNED_32, - RS_TYPE_SIGNED_64, - RS_TYPE_UNSIGNED_8, - RS_TYPE_UNSIGNED_16, - RS_TYPE_UNSIGNED_32, - RS_TYPE_UNSIGNED_64, - - RS_TYPE_BOOLEAN, - - RS_TYPE_UNSIGNED_5_6_5, - RS_TYPE_UNSIGNED_5_5_5_1, - RS_TYPE_UNSIGNED_4_4_4_4, - - RS_TYPE_MATRIX_4X4, - RS_TYPE_MATRIX_3X3, - RS_TYPE_MATRIX_2X2, - - RS_TYPE_ELEMENT = 1000, - RS_TYPE_TYPE, - RS_TYPE_ALLOCATION, - RS_TYPE_SAMPLER, - RS_TYPE_SCRIPT, - RS_TYPE_MESH, - RS_TYPE_PROGRAM_FRAGMENT, - RS_TYPE_PROGRAM_VERTEX, - RS_TYPE_PROGRAM_RASTER, - RS_TYPE_PROGRAM_STORE, -}; - -enum RsDataKind { - RS_KIND_USER, - - RS_KIND_PIXEL_L = 7, - RS_KIND_PIXEL_A, - RS_KIND_PIXEL_LA, - RS_KIND_PIXEL_RGB, - RS_KIND_PIXEL_RGBA, -}; - -enum RsSamplerParam { - RS_SAMPLER_MIN_FILTER, - RS_SAMPLER_MAG_FILTER, - RS_SAMPLER_WRAP_S, - RS_SAMPLER_WRAP_T, - RS_SAMPLER_WRAP_R, - RS_SAMPLER_ANISO -}; - -enum RsSamplerValue { - RS_SAMPLER_NEAREST, - RS_SAMPLER_LINEAR, - RS_SAMPLER_LINEAR_MIP_LINEAR, - RS_SAMPLER_WRAP, - RS_SAMPLER_CLAMP, - RS_SAMPLER_LINEAR_MIP_NEAREST, -}; - -enum RsTextureTarget { - RS_TEXTURE_2D, - RS_TEXTURE_CUBE -}; - -enum RsDimension { - RS_DIMENSION_X, - RS_DIMENSION_Y, - RS_DIMENSION_Z, - RS_DIMENSION_LOD, - RS_DIMENSION_FACE, - - RS_DIMENSION_ARRAY_0 = 100, - RS_DIMENSION_ARRAY_1, - RS_DIMENSION_ARRAY_2, - RS_DIMENSION_ARRAY_3, - RS_DIMENSION_MAX = RS_DIMENSION_ARRAY_3 -}; - -enum RsDepthFunc { - RS_DEPTH_FUNC_ALWAYS, - RS_DEPTH_FUNC_LESS, - RS_DEPTH_FUNC_LEQUAL, - RS_DEPTH_FUNC_GREATER, - RS_DEPTH_FUNC_GEQUAL, - RS_DEPTH_FUNC_EQUAL, - RS_DEPTH_FUNC_NOTEQUAL -}; - -enum RsBlendSrcFunc { - RS_BLEND_SRC_ZERO, // 0 - RS_BLEND_SRC_ONE, // 1 - RS_BLEND_SRC_DST_COLOR, // 2 - RS_BLEND_SRC_ONE_MINUS_DST_COLOR, // 3 - RS_BLEND_SRC_SRC_ALPHA, // 4 - RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5 - RS_BLEND_SRC_DST_ALPHA, // 6 - RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7 - RS_BLEND_SRC_SRC_ALPHA_SATURATE // 8 -}; - -enum RsBlendDstFunc { - RS_BLEND_DST_ZERO, // 0 - RS_BLEND_DST_ONE, // 1 - RS_BLEND_DST_SRC_COLOR, // 2 - RS_BLEND_DST_ONE_MINUS_SRC_COLOR, // 3 - RS_BLEND_DST_SRC_ALPHA, // 4 - RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5 - RS_BLEND_DST_DST_ALPHA, // 6 - RS_BLEND_DST_ONE_MINUS_DST_ALPHA // 7 -}; - -enum RsTexEnvMode { - RS_TEX_ENV_MODE_NONE, - RS_TEX_ENV_MODE_REPLACE, - RS_TEX_ENV_MODE_MODULATE, - RS_TEX_ENV_MODE_DECAL -}; - -enum RsProgramParam { - RS_PROGRAM_PARAM_INPUT, - RS_PROGRAM_PARAM_OUTPUT, - RS_PROGRAM_PARAM_CONSTANT, - RS_PROGRAM_PARAM_TEXTURE_TYPE, -}; - -enum RsPrimitive { - RS_PRIMITIVE_POINT, - RS_PRIMITIVE_LINE, - RS_PRIMITIVE_LINE_STRIP, - RS_PRIMITIVE_TRIANGLE, - RS_PRIMITIVE_TRIANGLE_STRIP, - RS_PRIMITIVE_TRIANGLE_FAN -}; - -enum RsError { - RS_ERROR_NONE = 0, - RS_ERROR_BAD_SHADER = 1, - RS_ERROR_BAD_SCRIPT = 2, - RS_ERROR_BAD_VALUE = 3, - RS_ERROR_OUT_OF_MEMORY = 4, - RS_ERROR_DRIVER = 5, - - RS_ERROR_FATAL_UNKNOWN = 0x1000, - RS_ERROR_FATAL_DRIVER = 0x1001, - RS_ERROR_FATAL_PROGRAM_LINK = 0x1002 -}; - -enum RsAnimationInterpolation { - RS_ANIMATION_INTERPOLATION_STEP, - RS_ANIMATION_INTERPOLATION_LINEAR, - RS_ANIMATION_INTERPOLATION_BEZIER, - RS_ANIMATION_INTERPOLATION_CARDINAL, - RS_ANIMATION_INTERPOLATION_HERMITE, - RS_ANIMATION_INTERPOLATION_BSPLINE -}; - -enum RsAnimationEdge { - RS_ANIMATION_EDGE_UNDEFINED, - RS_ANIMATION_EDGE_CONSTANT, - RS_ANIMATION_EDGE_GRADIENT, - RS_ANIMATION_EDGE_CYCLE, - RS_ANIMATION_EDGE_OSCILLATE, - RS_ANIMATION_EDGE_CYLE_RELATIVE -}; - -enum RsA3DClassID { - RS_A3D_CLASS_ID_UNKNOWN, - RS_A3D_CLASS_ID_MESH, - RS_A3D_CLASS_ID_TYPE, - RS_A3D_CLASS_ID_ELEMENT, - RS_A3D_CLASS_ID_ALLOCATION, - RS_A3D_CLASS_ID_PROGRAM_VERTEX, - RS_A3D_CLASS_ID_PROGRAM_RASTER, - RS_A3D_CLASS_ID_PROGRAM_FRAGMENT, - RS_A3D_CLASS_ID_PROGRAM_STORE, - RS_A3D_CLASS_ID_SAMPLER, - RS_A3D_CLASS_ID_ANIMATION, - RS_A3D_CLASS_ID_ADAPTER_1D, - RS_A3D_CLASS_ID_ADAPTER_2D, - RS_A3D_CLASS_ID_SCRIPT_C -}; - -enum RsCullMode { - RS_CULL_BACK, - RS_CULL_FRONT, - RS_CULL_NONE -}; - -typedef struct { - RsA3DClassID classID; - const char* objectName; -} RsFileIndexEntry; - -// Script to Script -typedef struct { - uint32_t xStart; - uint32_t xEnd; - uint32_t yStart; - uint32_t yEnd; - uint32_t zStart; - uint32_t zEnd; - uint32_t arrayStart; - uint32_t arrayEnd; - -} RsScriptCall; - +// // A3D loading and object update code. // Should only be called at object creation, not thread safe RsObjectBase rsaFileA3DGetEntryByIndex(RsContext, uint32_t idx, RsFile); diff --git a/libs/rs/RenderScriptDefines.h b/libs/rs/RenderScriptDefines.h new file mode 100644 index 000000000000..4e1ac88094dd --- /dev/null +++ b/libs/rs/RenderScriptDefines.h @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2007 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 RENDER_SCRIPT_DEFINES_H +#define RENDER_SCRIPT_DEFINES_H + +#include <stdint.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////// +// + +typedef void * RsAsyncVoidPtr; + +typedef void * RsAdapter1D; +typedef void * RsAdapter2D; +typedef void * RsAllocation; +typedef void * RsAnimation; +typedef void * RsContext; +typedef void * RsDevice; +typedef void * RsElement; +typedef void * RsFile; +typedef void * RsFont; +typedef void * RsSampler; +typedef void * RsScript; +typedef void * RsMesh; +typedef void * RsType; +typedef void * RsObjectBase; + +typedef void * RsProgram; +typedef void * RsProgramVertex; +typedef void * RsProgramFragment; +typedef void * RsProgramStore; +typedef void * RsProgramRaster; + +typedef void (* RsBitmapCallback_t)(void *); + +enum RsDeviceParam { + RS_DEVICE_PARAM_FORCE_SOFTWARE_GL, + RS_DEVICE_PARAM_COUNT +}; + +typedef struct { + uint32_t colorMin; + uint32_t colorPref; + uint32_t alphaMin; + uint32_t alphaPref; + uint32_t depthMin; + uint32_t depthPref; + uint32_t stencilMin; + uint32_t stencilPref; + uint32_t samplesMin; + uint32_t samplesPref; + float samplesQ; +} RsSurfaceConfig; + +enum RsMessageToClientType { + RS_MESSAGE_TO_CLIENT_NONE = 0, + RS_MESSAGE_TO_CLIENT_EXCEPTION = 1, + RS_MESSAGE_TO_CLIENT_RESIZE = 2, + RS_MESSAGE_TO_CLIENT_ERROR = 3, + RS_MESSAGE_TO_CLIENT_USER = 4 +}; + +enum RsAllocationUsageType { + RS_ALLOCATION_USAGE_SCRIPT = 0x0001, + RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE = 0x0002, + RS_ALLOCATION_USAGE_GRAPHICS_VERTEX = 0x0004, + RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS = 0x0008, + + RS_ALLOCATION_USAGE_ALL = 0x000F +}; + +enum RsAllocationMipmapControl { + RS_ALLOCATION_MIPMAP_NONE = 0, + RS_ALLOCATION_MIPMAP_FULL = 1, + RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE = 2 +}; + +enum RsAllocationCubemapFace { + RS_ALLOCATION_CUBMAP_FACE_POSITVE_X = 0, + RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_X = 1, + RS_ALLOCATION_CUBMAP_FACE_POSITVE_Y = 2, + RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Y = 3, + RS_ALLOCATION_CUBMAP_FACE_POSITVE_Z = 4, + RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Z = 5 +}; + +enum RsDataType { + RS_TYPE_NONE, + RS_TYPE_FLOAT_16, + RS_TYPE_FLOAT_32, + RS_TYPE_FLOAT_64, + RS_TYPE_SIGNED_8, + RS_TYPE_SIGNED_16, + RS_TYPE_SIGNED_32, + RS_TYPE_SIGNED_64, + RS_TYPE_UNSIGNED_8, + RS_TYPE_UNSIGNED_16, + RS_TYPE_UNSIGNED_32, + RS_TYPE_UNSIGNED_64, + + RS_TYPE_BOOLEAN, + + RS_TYPE_UNSIGNED_5_6_5, + RS_TYPE_UNSIGNED_5_5_5_1, + RS_TYPE_UNSIGNED_4_4_4_4, + + RS_TYPE_MATRIX_4X4, + RS_TYPE_MATRIX_3X3, + RS_TYPE_MATRIX_2X2, + + RS_TYPE_ELEMENT = 1000, + RS_TYPE_TYPE, + RS_TYPE_ALLOCATION, + RS_TYPE_SAMPLER, + RS_TYPE_SCRIPT, + RS_TYPE_MESH, + RS_TYPE_PROGRAM_FRAGMENT, + RS_TYPE_PROGRAM_VERTEX, + RS_TYPE_PROGRAM_RASTER, + RS_TYPE_PROGRAM_STORE, +}; + +enum RsDataKind { + RS_KIND_USER, + + RS_KIND_PIXEL_L = 7, + RS_KIND_PIXEL_A, + RS_KIND_PIXEL_LA, + RS_KIND_PIXEL_RGB, + RS_KIND_PIXEL_RGBA, +}; + +enum RsSamplerParam { + RS_SAMPLER_MIN_FILTER, + RS_SAMPLER_MAG_FILTER, + RS_SAMPLER_WRAP_S, + RS_SAMPLER_WRAP_T, + RS_SAMPLER_WRAP_R, + RS_SAMPLER_ANISO +}; + +enum RsSamplerValue { + RS_SAMPLER_NEAREST, + RS_SAMPLER_LINEAR, + RS_SAMPLER_LINEAR_MIP_LINEAR, + RS_SAMPLER_WRAP, + RS_SAMPLER_CLAMP, + RS_SAMPLER_LINEAR_MIP_NEAREST, +}; + +enum RsTextureTarget { + RS_TEXTURE_2D, + RS_TEXTURE_CUBE +}; + +enum RsDimension { + RS_DIMENSION_X, + RS_DIMENSION_Y, + RS_DIMENSION_Z, + RS_DIMENSION_LOD, + RS_DIMENSION_FACE, + + RS_DIMENSION_ARRAY_0 = 100, + RS_DIMENSION_ARRAY_1, + RS_DIMENSION_ARRAY_2, + RS_DIMENSION_ARRAY_3, + RS_DIMENSION_MAX = RS_DIMENSION_ARRAY_3 +}; + +enum RsDepthFunc { + RS_DEPTH_FUNC_ALWAYS, + RS_DEPTH_FUNC_LESS, + RS_DEPTH_FUNC_LEQUAL, + RS_DEPTH_FUNC_GREATER, + RS_DEPTH_FUNC_GEQUAL, + RS_DEPTH_FUNC_EQUAL, + RS_DEPTH_FUNC_NOTEQUAL +}; + +enum RsBlendSrcFunc { + RS_BLEND_SRC_ZERO, // 0 + RS_BLEND_SRC_ONE, // 1 + RS_BLEND_SRC_DST_COLOR, // 2 + RS_BLEND_SRC_ONE_MINUS_DST_COLOR, // 3 + RS_BLEND_SRC_SRC_ALPHA, // 4 + RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5 + RS_BLEND_SRC_DST_ALPHA, // 6 + RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7 + RS_BLEND_SRC_SRC_ALPHA_SATURATE // 8 +}; + +enum RsBlendDstFunc { + RS_BLEND_DST_ZERO, // 0 + RS_BLEND_DST_ONE, // 1 + RS_BLEND_DST_SRC_COLOR, // 2 + RS_BLEND_DST_ONE_MINUS_SRC_COLOR, // 3 + RS_BLEND_DST_SRC_ALPHA, // 4 + RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5 + RS_BLEND_DST_DST_ALPHA, // 6 + RS_BLEND_DST_ONE_MINUS_DST_ALPHA // 7 +}; + +enum RsTexEnvMode { + RS_TEX_ENV_MODE_NONE, + RS_TEX_ENV_MODE_REPLACE, + RS_TEX_ENV_MODE_MODULATE, + RS_TEX_ENV_MODE_DECAL +}; + +enum RsProgramParam { + RS_PROGRAM_PARAM_INPUT, + RS_PROGRAM_PARAM_OUTPUT, + RS_PROGRAM_PARAM_CONSTANT, + RS_PROGRAM_PARAM_TEXTURE_TYPE, +}; + +enum RsPrimitive { + RS_PRIMITIVE_POINT, + RS_PRIMITIVE_LINE, + RS_PRIMITIVE_LINE_STRIP, + RS_PRIMITIVE_TRIANGLE, + RS_PRIMITIVE_TRIANGLE_STRIP, + RS_PRIMITIVE_TRIANGLE_FAN +}; + +enum RsError { + RS_ERROR_NONE = 0, + RS_ERROR_BAD_SHADER = 1, + RS_ERROR_BAD_SCRIPT = 2, + RS_ERROR_BAD_VALUE = 3, + RS_ERROR_OUT_OF_MEMORY = 4, + RS_ERROR_DRIVER = 5, + + RS_ERROR_FATAL_UNKNOWN = 0x1000, + RS_ERROR_FATAL_DRIVER = 0x1001, + RS_ERROR_FATAL_PROGRAM_LINK = 0x1002 +}; + +enum RsAnimationInterpolation { + RS_ANIMATION_INTERPOLATION_STEP, + RS_ANIMATION_INTERPOLATION_LINEAR, + RS_ANIMATION_INTERPOLATION_BEZIER, + RS_ANIMATION_INTERPOLATION_CARDINAL, + RS_ANIMATION_INTERPOLATION_HERMITE, + RS_ANIMATION_INTERPOLATION_BSPLINE +}; + +enum RsAnimationEdge { + RS_ANIMATION_EDGE_UNDEFINED, + RS_ANIMATION_EDGE_CONSTANT, + RS_ANIMATION_EDGE_GRADIENT, + RS_ANIMATION_EDGE_CYCLE, + RS_ANIMATION_EDGE_OSCILLATE, + RS_ANIMATION_EDGE_CYLE_RELATIVE +}; + +enum RsA3DClassID { + RS_A3D_CLASS_ID_UNKNOWN, + RS_A3D_CLASS_ID_MESH, + RS_A3D_CLASS_ID_TYPE, + RS_A3D_CLASS_ID_ELEMENT, + RS_A3D_CLASS_ID_ALLOCATION, + RS_A3D_CLASS_ID_PROGRAM_VERTEX, + RS_A3D_CLASS_ID_PROGRAM_RASTER, + RS_A3D_CLASS_ID_PROGRAM_FRAGMENT, + RS_A3D_CLASS_ID_PROGRAM_STORE, + RS_A3D_CLASS_ID_SAMPLER, + RS_A3D_CLASS_ID_ANIMATION, + RS_A3D_CLASS_ID_ADAPTER_1D, + RS_A3D_CLASS_ID_ADAPTER_2D, + RS_A3D_CLASS_ID_SCRIPT_C +}; + +enum RsCullMode { + RS_CULL_BACK, + RS_CULL_FRONT, + RS_CULL_NONE +}; + +typedef struct { + RsA3DClassID classID; + const char* objectName; +} RsFileIndexEntry; + +// Script to Script +typedef struct { + uint32_t xStart; + uint32_t xEnd; + uint32_t yStart; + uint32_t yEnd; + uint32_t zStart; + uint32_t zEnd; + uint32_t arrayStart; + uint32_t arrayEnd; + +} RsScriptCall; + +#ifdef __cplusplus +}; +#endif + +#endif // RENDER_SCRIPT_DEFINES_H + + + + diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp new file mode 100644 index 000000000000..6c5a55be85ed --- /dev/null +++ b/libs/rs/driver/rsdBcc.cpp @@ -0,0 +1,549 @@ +/* + * 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 "rsdCore.h" +#include "rsdBcc.h" + +#include "rsContext.h" +#include "rsScriptC.h" + +#include "utils/Timers.h" +#include "utils/StopWatch.h" +extern "C" { +#include "libdex/ZipArchive.h" +} + + +using namespace android; +using namespace android::renderscript; + +struct DrvScript { + int (*mRoot)(); + void (*mInit)(); + + BCCScriptRef mBccScript; + + uint32_t mInvokeFunctionCount; + InvokeFunc_t *mInvokeFunctions; + uint32_t mFieldCount; + void ** mFieldAddress; + bool * mFieldIsObject; + + const uint8_t * mScriptText; + uint32_t mScriptTextLength; + + //uint32_t * mObjectSlots; + //uint32_t mObjectSlotCount; + + uint32_t mPragmaCount; + const char ** mPragmaKeys; + const char ** mPragmaValues; + +}; + +static Script * setTLS(Script *sc) { + ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); + rsAssert(tls); + Script *old = tls->mScript; + tls->mScript = sc; + return old; +} + + +// Input: cacheDir +// Input: resName +// Input: extName +// +// Note: cacheFile = resName + extName +// +// Output: Returns cachePath == cacheDir + cacheFile +static char *genCacheFileName(const char *cacheDir, + const char *resName, + const char *extName) { + char cachePath[512]; + char cacheFile[sizeof(cachePath)]; + const size_t kBufLen = sizeof(cachePath) - 1; + + cacheFile[0] = '\0'; + // Note: resName today is usually something like + // "/com.android.fountain:raw/fountain" + if (resName[0] != '/') { + // Get the absolute path of the raw/***.bc file. + + // Generate the absolute path. This doesn't do everything it + // should, e.g. if resName is "./out/whatever" it doesn't crunch + // the leading "./" out because this if-block is not triggered, + // but it'll make do. + // + if (getcwd(cacheFile, kBufLen) == NULL) { + LOGE("Can't get CWD while opening raw/***.bc file\n"); + return NULL; + } + // Append "/" at the end of cacheFile so far. + strncat(cacheFile, "/", kBufLen); + } + + // cacheFile = resName + extName + // + strncat(cacheFile, resName, kBufLen); + if (extName != NULL) { + // TODO(srhines): strncat() is a bit dangerous + strncat(cacheFile, extName, kBufLen); + } + + // Turn the path into a flat filename by replacing + // any slashes after the first one with '@' characters. + char *cp = cacheFile + 1; + while (*cp != '\0') { + if (*cp == '/') { + *cp = '@'; + } + cp++; + } + + // Tack on the file name for the actual cache file path. + strncpy(cachePath, cacheDir, kBufLen); + strncat(cachePath, cacheFile, kBufLen); + + LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath); + return strdup(cachePath); +} + +bool rsdScriptInit(const Context *rsc, + ScriptC *script, + char const *resName, + char const *cacheDir, + uint8_t const *bitcode, + size_t bitcodeSize, + uint32_t flags, + RsHalSymbolLookupFunc lookupFunc) { + //LOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc); + + char *cachePath = NULL; + uint32_t objectSlotCount = 0; + + DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript)); + if (drv == NULL) { + return false; + } + script->mHal.drv = drv; + + drv->mBccScript = bccCreateScript(); + script->mHal.info.isThreadable = true; + drv->mScriptText = bitcode; + drv->mScriptTextLength = bitcodeSize; + + //LOGE("mBccScript %p", script->mBccScript); + + if (bccRegisterSymbolCallback(drv->mBccScript, lookupFunc, script) != 0) { + LOGE("bcc: FAILS to register symbol callback"); + goto error; + } + + if (bccReadBC(drv->mBccScript, + resName, + (char const *)drv->mScriptText, + drv->mScriptTextLength, 0) != 0) { + LOGE("bcc: FAILS to read bitcode"); + return NULL; + } + +#if 1 + if (bccLinkFile(drv->mBccScript, "/system/lib/libclcore.bc", 0) != 0) { + LOGE("bcc: FAILS to link bitcode"); + return NULL; + } +#endif + cachePath = genCacheFileName(cacheDir, resName, ".oBCC"); + + if (bccPrepareExecutable(drv->mBccScript, cachePath, 0) != 0) { + LOGE("bcc: FAILS to prepare executable"); + return NULL; + } + + free(cachePath); + + drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root")); + drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init")); + + drv->mInvokeFunctionCount = bccGetExportFuncCount(drv->mBccScript); + if (drv->mInvokeFunctionCount <= 0) + drv->mInvokeFunctions = NULL; + else { + drv->mInvokeFunctions = (InvokeFunc_t*) calloc(drv->mInvokeFunctionCount, sizeof(InvokeFunc_t)); + bccGetExportFuncList(drv->mBccScript, drv->mInvokeFunctionCount, (void **) drv->mInvokeFunctions); + } + + drv->mFieldCount = bccGetExportVarCount(drv->mBccScript); + if (drv->mFieldCount <= 0) { + drv->mFieldAddress = NULL; + drv->mFieldIsObject = NULL; + } else { + drv->mFieldAddress = (void **) calloc(drv->mFieldCount, sizeof(void *)); + drv->mFieldIsObject = (bool *) calloc(drv->mFieldCount, sizeof(bool)); + bccGetExportVarList(drv->mBccScript, drv->mFieldCount, (void **) drv->mFieldAddress); + } + + objectSlotCount = bccGetObjectSlotCount(drv->mBccScript); + if (objectSlotCount) { + uint32_t * slots = new uint32_t[objectSlotCount]; + bccGetObjectSlotList(drv->mBccScript, objectSlotCount, slots); + for (uint32_t ct=0; ct < objectSlotCount; ct++) { + drv->mFieldIsObject[slots[ct]] = true; + } + delete [] slots; + } + + uint32_t mPragmaCount; + const char ** mPragmaKeys; + const char ** mPragmaValues; + + const static int pragmaMax = 16; + drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript); + if (drv->mPragmaCount <= 0) { + drv->mPragmaKeys = NULL; + drv->mPragmaValues = NULL; + } else { + drv->mPragmaKeys = (const char **) calloc(drv->mFieldCount, sizeof(const char *)); + drv->mPragmaValues = (const char **) calloc(drv->mFieldCount, sizeof(const char *)); + bccGetPragmaList(drv->mBccScript, drv->mPragmaCount, drv->mPragmaKeys, drv->mPragmaValues); + } + + + + // Copy info over to runtime + script->mHal.info.exportedFunctionCount = drv->mInvokeFunctionCount; + script->mHal.info.exportedVariableCount = drv->mFieldCount; + script->mHal.info.exportedPragmaCount = drv->mPragmaCount; + script->mHal.info.exportedPragmaKeyList = drv->mPragmaKeys; + script->mHal.info.exportedPragmaValueList = drv->mPragmaValues; + script->mHal.info.root = drv->mRoot; + + + return true; + +error: + + free(drv); + return false; + +} + +typedef struct { + Context *rsc; + Script *script; + const Allocation * ain; + Allocation * aout; + const void * usr; + + uint32_t mSliceSize; + volatile int mSliceNum; + + const uint8_t *ptrIn; + uint32_t eStrideIn; + uint8_t *ptrOut; + uint32_t eStrideOut; + + uint32_t xStart; + uint32_t xEnd; + uint32_t yStart; + uint32_t yEnd; + uint32_t zStart; + uint32_t zEnd; + uint32_t arrayStart; + uint32_t arrayEnd; + + uint32_t dimX; + uint32_t dimY; + uint32_t dimZ; + uint32_t dimArray; +} MTLaunchStruct; +typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t); + +static void wc_xy(void *usr, uint32_t idx) { + MTLaunchStruct *mtls = (MTLaunchStruct *)usr; + + while (1) { + uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); + uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize; + uint32_t yEnd = yStart + mtls->mSliceSize; + yEnd = rsMin(yEnd, mtls->yEnd); + if (yEnd <= yStart) { + return; + } + + //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd); + //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut); + for (uint32_t y = yStart; y < yEnd; y++) { + uint32_t offset = mtls->dimX * y; + uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset); + const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset); + + for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) { + ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0); + xPtrIn += mtls->eStrideIn; + xPtrOut += mtls->eStrideOut; + } + } + } +} + +static void wc_x(void *usr, uint32_t idx) { + MTLaunchStruct *mtls = (MTLaunchStruct *)usr; + + while (1) { + uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); + uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize; + uint32_t xEnd = xStart + mtls->mSliceSize; + xEnd = rsMin(xEnd, mtls->xEnd); + if (xEnd <= xStart) { + return; + } + + //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd); + //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut); + uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart); + const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart); + for (uint32_t x = xStart; x < xEnd; x++) { + ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0); + xPtrIn += mtls->eStrideIn; + xPtrOut += mtls->eStrideOut; + } + } +} + +void rsdScriptInvokeForEach(const Context *rsc, + Script *s, + const Allocation * ain, + Allocation * aout, + const void * usr, + uint32_t usrLen, + const RsScriptCall *sc) { + + RsHal * dc = (RsHal *)rsc->mHal.drv; + + MTLaunchStruct mtls; + memset(&mtls, 0, sizeof(mtls)); + + if (ain) { + mtls.dimX = ain->getType()->getDimX(); + mtls.dimY = ain->getType()->getDimY(); + mtls.dimZ = ain->getType()->getDimZ(); + //mtls.dimArray = ain->getType()->getDimArray(); + } else if (aout) { + mtls.dimX = aout->getType()->getDimX(); + mtls.dimY = aout->getType()->getDimY(); + mtls.dimZ = aout->getType()->getDimZ(); + //mtls.dimArray = aout->getType()->getDimArray(); + } else { + rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); + return; + } + + if (!sc || (sc->xEnd == 0)) { + mtls.xEnd = mtls.dimX; + } else { + rsAssert(sc->xStart < mtls.dimX); + rsAssert(sc->xEnd <= mtls.dimX); + rsAssert(sc->xStart < sc->xEnd); + mtls.xStart = rsMin(mtls.dimX, sc->xStart); + mtls.xEnd = rsMin(mtls.dimX, sc->xEnd); + if (mtls.xStart >= mtls.xEnd) return; + } + + if (!sc || (sc->yEnd == 0)) { + mtls.yEnd = mtls.dimY; + } else { + rsAssert(sc->yStart < mtls.dimY); + rsAssert(sc->yEnd <= mtls.dimY); + rsAssert(sc->yStart < sc->yEnd); + mtls.yStart = rsMin(mtls.dimY, sc->yStart); + mtls.yEnd = rsMin(mtls.dimY, sc->yEnd); + if (mtls.yStart >= mtls.yEnd) return; + } + + mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd); + mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd); + mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd); + mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd); + + rsAssert(ain->getType()->getDimZ() == 0); + + Context *mrsc = (Context *)rsc; + Script * oldTLS = setTLS(s); + + mtls.rsc = mrsc; + mtls.ain = ain; + mtls.aout = aout; + mtls.script = s; + mtls.usr = usr; + mtls.mSliceSize = 10; + mtls.mSliceNum = 0; + + mtls.ptrIn = NULL; + mtls.eStrideIn = 0; + if (ain) { + mtls.ptrIn = (const uint8_t *)ain->getPtr(); + mtls.eStrideIn = ain->getType()->getElementSizeBytes(); + } + + mtls.ptrOut = NULL; + mtls.eStrideOut = 0; + if (aout) { + mtls.ptrOut = (uint8_t *)aout->getPtr(); + mtls.eStrideOut = aout->getType()->getElementSizeBytes(); + } + + if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable) { + if (mtls.dimY > 1) { + rsdLaunchThreads(mrsc, wc_xy, &mtls); + } else { + rsdLaunchThreads(mrsc, wc_x, &mtls); + } + + //LOGE("launch 1"); + } else { + //LOGE("launch 3"); + for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) { + for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) { + for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) { + uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar + + mtls.dimX * mtls.dimY * z + + mtls.dimX * y; + uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset); + const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset); + + for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) { + ((rs_t)s->mHal.info.root) (xPtrIn, xPtrOut, usr, x, y, z, ar); + xPtrIn += mtls.eStrideIn; + xPtrOut += mtls.eStrideOut; + } + } + } + } + } + + setTLS(oldTLS); +} + + +int rsdScriptInvokeRoot(const Context *dc, Script *script) { + DrvScript *drv = (DrvScript *)script->mHal.drv; + + Script * oldTLS = setTLS(script); + int ret = drv->mRoot(); + setTLS(oldTLS); + + return ret; +} + +void rsdScriptInvokeInit(const Context *dc, Script *script) { + DrvScript *drv = (DrvScript *)script->mHal.drv; + + if (drv->mInit) { + drv->mInit(); + } +} + + +void rsdScriptInvokeFunction(const Context *dc, Script *script, + uint32_t slot, + const void *params, + size_t paramLength) { + DrvScript *drv = (DrvScript *)script->mHal.drv; + //LOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength); + + Script * oldTLS = setTLS(script); + ((void (*)(const void *, uint32_t)) + drv->mInvokeFunctions[slot])(params, paramLength); + setTLS(oldTLS); +} + +void rsdScriptSetGlobalVar(const Context *dc, const Script *script, + uint32_t slot, void *data, size_t dataLength) { + DrvScript *drv = (DrvScript *)script->mHal.drv; + //rsAssert(!script->mFieldIsObject[slot]); + //LOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); + + int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; + if (!destPtr) { + //LOGV("Calling setVar on slot = %i which is null", slot); + return; + } + + memcpy(destPtr, data, dataLength); +} + +void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, void *data) { + DrvScript *drv = (DrvScript *)script->mHal.drv; + //rsAssert(!script->mFieldIsObject[slot]); + //LOGE("setGlobalBind %p %p %i %p", dc, script, slot, data); + + int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; + if (!destPtr) { + //LOGV("Calling setVar on slot = %i which is null", slot); + return; + } + + memcpy(destPtr, &data, sizeof(void *)); +} + +void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) { + DrvScript *drv = (DrvScript *)script->mHal.drv; + //rsAssert(script->mFieldIsObject[slot]); + //LOGE("setGlobalObj %p %p %i %p", dc, script, slot, data); + + int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; + if (!destPtr) { + //LOGV("Calling setVar on slot = %i which is null", slot); + return; + } + + rsiSetObject((ObjectBase **)destPtr, data); +} + +void rsdScriptDestroy(const Context *dc, Script *script) { + DrvScript *drv = (DrvScript *)script->mHal.drv; + + if (drv->mFieldAddress) { + for (size_t ct=0; ct < drv->mFieldCount; ct++) { + if (drv->mFieldIsObject[ct]) { + // The field address can be NULL if the script-side has + // optimized the corresponding global variable away. + if (drv->mFieldAddress[ct]) { + rsiClearObject((ObjectBase **)drv->mFieldAddress[ct]); + } + } + } + delete [] drv->mFieldAddress; + delete [] drv->mFieldIsObject; + drv->mFieldAddress = NULL; + drv->mFieldIsObject = NULL; + drv->mFieldCount = 0; + } + + if (drv->mInvokeFunctions) { + delete [] drv->mInvokeFunctions; + drv->mInvokeFunctions = NULL; + drv->mInvokeFunctionCount = 0; + } + free(drv); + script->mHal.drv = NULL; + +} + + diff --git a/libs/rs/driver/rsdBcc.h b/libs/rs/driver/rsdBcc.h new file mode 100644 index 000000000000..6723a3640fd0 --- /dev/null +++ b/libs/rs/driver/rsdBcc.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009 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_BCC_H +#define RSD_BCC_H + +#include <rs_hal.h> + + +bool rsdScriptInit(const android::renderscript::Context *, android::renderscript::ScriptC *, + char const *resName, char const *cacheDir, + uint8_t const *bitcode, size_t bitcodeSize, + uint32_t flags, android::renderscript::RsHalSymbolLookupFunc lookupFunc); +void rsdScriptInvokeFunction(const android::renderscript::Context *dc, + android::renderscript::Script *script, + uint32_t slot, + const void *params, + size_t paramLength); + +void rsdScriptInvokeForEach(const android::renderscript::Context *rsc, + android::renderscript::Script *s, + const android::renderscript::Allocation * ain, + android::renderscript::Allocation * aout, + const void * usr, + uint32_t usrLen, + const RsScriptCall *sc); + +int rsdScriptInvokeRoot(const android::renderscript::Context *dc, + android::renderscript::Script *script); +void rsdScriptInvokeInit(const android::renderscript::Context *dc, + android::renderscript::Script *script); + +void rsdScriptSetGlobalVar(const android::renderscript::Context *, + const android::renderscript::Script *, + uint32_t slot, void *data, size_t dataLen); +void rsdScriptSetGlobalBind(const android::renderscript::Context *, + const android::renderscript::Script *, + uint32_t slot, void *data); +void rsdScriptSetGlobalObj(const android::renderscript::Context *, + const android::renderscript::Script *, + uint32_t slot, android::renderscript::ObjectBase *data); + +void rsdScriptSetGlobal(const android::renderscript::Context *dc, + const android::renderscript::Script *script, + uint32_t slot, + void *data, + size_t dataLength); +void rsdScriptGetGlobal(const android::renderscript::Context *dc, + const android::renderscript::Script *script, + uint32_t slot, + void *data, + size_t dataLength); +void rsdScriptDestroy(const android::renderscript::Context *dc, + android::renderscript::Script *script); + + +#endif diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp new file mode 100644 index 000000000000..65461107028a --- /dev/null +++ b/libs/rs/driver/rsdCore.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2009 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 "rsdCore.h" +#include "rsdBcc.h" + +#include <malloc.h> +#include "rsContext.h" + +#include <sys/types.h> +#include <sys/resource.h> +#include <sched.h> +#include <cutils/properties.h> +#include <cutils/sched_policy.h> +#include <sys/syscall.h> +#include <string.h> + +using namespace android; +using namespace android::renderscript; + +static void Shutdown(Context *rsc); +static void SetPriority(const Context *rsc, int32_t priority); + +static RsdHalFunctions FunctionTable = { + Shutdown, + NULL, + SetPriority, + { + rsdScriptInit, + rsdScriptInvokeFunction, + rsdScriptInvokeRoot, + rsdScriptInvokeForEach, + rsdScriptInvokeInit, + rsdScriptSetGlobalVar, + rsdScriptSetGlobalBind, + rsdScriptSetGlobalObj, + rsdScriptDestroy + } +}; + + + +static void * HelperThreadProc(void *vrsc) { + Context *rsc = static_cast<Context *>(vrsc); + RsHal *dc = (RsHal *)rsc->mHal.drv; + + + uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount); + + //LOGV("RS helperThread starting %p idx=%i", rsc, idx); + + dc->mWorkers.mLaunchSignals[idx].init(); + dc->mWorkers.mNativeThreadId[idx] = gettid(); + +#if 0 + typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t; + cpu_set_t cpuset; + memset(&cpuset, 0, sizeof(cpuset)); + cpuset.bits[idx / 64] |= 1ULL << (idx % 64); + int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx], + sizeof(cpuset), &cpuset); + LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret)); +#endif + + int status = pthread_setspecific(rsc->gThreadTLSKey, rsc->mTlsStruct); + if (status) { + LOGE("pthread_setspecific %i", status); + } + + while (!dc->mExit) { + dc->mWorkers.mLaunchSignals[idx].wait(); + if (dc->mWorkers.mLaunchCallback) { + dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx); + } + android_atomic_dec(&dc->mWorkers.mRunningCount); + dc->mWorkers.mCompleteSignal.set(); + } + + //LOGV("RS helperThread exited %p idx=%i", rsc, idx); + return NULL; +} + +void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) { + RsHal *dc = (RsHal *)rsc->mHal.drv; + + dc->mWorkers.mLaunchData = data; + dc->mWorkers.mLaunchCallback = cbk; + android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); + for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { + dc->mWorkers.mLaunchSignals[ct].set(); + } + while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { + dc->mWorkers.mCompleteSignal.wait(); + } +} + +bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) { + rsc->mHal.funcs = FunctionTable; + + RsHal *dc = (RsHal *)calloc(1, sizeof(RsHal)); + if (!dc) { + LOGE("Calloc for driver hal failed."); + return false; + } + rsc->mHal.drv = dc; + + + int cpu = sysconf(_SC_NPROCESSORS_ONLN); + LOGV("RS Launching thread(s), reported CPU count %i", cpu); + if (cpu < 2) cpu = 0; + + dc->mWorkers.mCount = (uint32_t)cpu; + dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t)); + dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t)); + dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount]; + dc->mWorkers.mLaunchCallback = NULL; + + dc->mWorkers.mCompleteSignal.init(); + + android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); + android_atomic_release_store(0, &dc->mWorkers.mLaunchCount); + + int status; + pthread_attr_t threadAttr; + status = pthread_attr_init(&threadAttr); + if (status) { + LOGE("Failed to init thread attribute."); + return false; + } + + for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { + status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc); + if (status) { + dc->mWorkers.mCount = ct; + LOGE("Created fewer than expected number of RS threads."); + break; + } + } + while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { + usleep(100); + } + + pthread_attr_destroy(&threadAttr); + return true; +} + + +void SetPriority(const Context *rsc, int32_t priority) { + RsHal *dc = (RsHal *)rsc->mHal.drv; + for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { + setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority); + } +} + +void Shutdown(Context *rsc) { + RsHal *dc = (RsHal *)rsc->mHal.drv; + + dc->mExit = true; + dc->mWorkers.mLaunchData = NULL; + dc->mWorkers.mLaunchCallback = NULL; + android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); + for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { + dc->mWorkers.mLaunchSignals[ct].set(); + } + int status; + void *res; + for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { + status = pthread_join(dc->mWorkers.mThreadId[ct], &res); + } + rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0); +} + + diff --git a/libs/rs/driver/rsdCore.h b/libs/rs/driver/rsdCore.h new file mode 100644 index 000000000000..02b2fbc5441c --- /dev/null +++ b/libs/rs/driver/rsdCore.h @@ -0,0 +1,55 @@ +/* + * 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_CORE_H +#define RSD_CORE_H + +#include <rs_hal.h> +#include <bcc/bcc.h> + +#include "rsMutex.h" +#include "rsSignal.h" + + +typedef void (* InvokeFunc_t)(void); +typedef void (*WorkerCallback_t)(void *usr, uint32_t idx); + +typedef struct RsHalRec { + uint32_t version_major; + uint32_t version_minor; + + struct Workers { + volatile int mRunningCount; + volatile int mLaunchCount; + uint32_t mCount; + pthread_t *mThreadId; + pid_t *mNativeThreadId; + android::renderscript::Signal mCompleteSignal; + + android::renderscript::Signal *mLaunchSignals; + WorkerCallback_t mLaunchCallback; + void *mLaunchData; + }; + Workers mWorkers; + bool mExit; +} RsHal; + + + +void rsdLaunchThreads(android::renderscript::Context *rsc, WorkerCallback_t cbk, void *data); + +#endif + diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index 7e23cec90805..bbb62007b13f 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -181,10 +181,6 @@ ScriptBindAllocation { } -ScriptCBegin { - } - - ScriptSetTimeZone { param RsScript s param const char * timeZone @@ -246,15 +242,11 @@ ScriptSetVarV { } -ScriptCSetText { - param const char * text - param uint32_t length - } - ScriptCCreate { - param const char * packageName param const char * resName param const char * cacheDir + param const char * text + param uint32_t length ret RsScript } diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index ec03a158871f..b8ddb0b7cac2 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -29,21 +29,22 @@ Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages, : ObjectBase(rsc) { init(rsc, type); - mUsageFlags = usages; - mMipmapControl = mc; + mHal.state.usageFlags = usages; + mHal.state.mipmapControl = mc; allocScriptMemory(); - if (mType->getElement()->getHasReferences()) { - memset(mPtr, 0, mType->getSizeBytes()); + if (mHal.state.type->getElement()->getHasReferences()) { + memset(mHal.state.mallocPtr, 0, mHal.state.type->getSizeBytes()); } - if (!mPtr) { + if (!mHal.state.mallocPtr) { LOGE("Allocation::Allocation, alloc failure"); } } void Allocation::init(Context *rsc, const Type *type) { - mPtr = NULL; + memset(&mHal, 0, sizeof(mHal)); + mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE; mCpuWrite = false; mCpuRead = false; @@ -52,8 +53,6 @@ void Allocation::init(Context *rsc, const Type *type) { mReadWriteRatio = 0; mUpdateSize = 0; - mUsageFlags = 0; - mMipmapControl = RS_ALLOCATION_MIPMAP_NONE; mTextureID = 0; mBufferID = 0; @@ -62,16 +61,25 @@ void Allocation::init(Context *rsc, const Type *type) { mUserBitmapCallback = NULL; mUserBitmapCallbackData = NULL; - mType.set(type); - rsAssert(type); + mHal.state.type.set(type); + updateCache(); +} - mPtr = NULL; +void Allocation::updateCache() { + const Type *type = mHal.state.type.get(); + mHal.state.dimensionX = type->getDimX(); + mHal.state.dimensionY = type->getDimY(); + mHal.state.dimensionZ = type->getDimZ(); + mHal.state.hasFaces = type->getDimFaces(); + mHal.state.hasMipmaps = type->getDimLOD(); + mHal.state.elementSizeBytes = type->getElementSizeBytes(); + mHal.state.hasReferences = mHal.state.type->getElement()->getHasReferences(); } Allocation::~Allocation() { if (mUserBitmapCallback != NULL) { mUserBitmapCallback(mUserBitmapCallbackData); - mPtr = NULL; + mHal.state.mallocPtr = NULL; } freeScriptMemory(); #ifndef ANDROID_RS_SERIALIZE @@ -105,14 +113,14 @@ bool Allocation::fixAllocation() { } void Allocation::deferedUploadToTexture(const Context *rsc) { - mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE; + mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE; mUploadDefered = true; } uint32_t Allocation::getGLTarget() const { #ifndef ANDROID_RS_SERIALIZE if (getIsTexture()) { - if (mType->getDimFaces()) { + if (mHal.state.type->getDimFaces()) { return GL_TEXTURE_CUBE_MAP; } else { return GL_TEXTURE_2D; @@ -126,14 +134,14 @@ uint32_t Allocation::getGLTarget() const { } void Allocation::allocScriptMemory() { - rsAssert(!mPtr); - mPtr = malloc(mType->getSizeBytes()); + rsAssert(!mHal.state.mallocPtr); + mHal.state.mallocPtr = malloc(mHal.state.type->getSizeBytes()); } void Allocation::freeScriptMemory() { - if (mPtr) { - free(mPtr); - mPtr = NULL; + if (mHal.state.mallocPtr) { + free(mHal.state.mallocPtr); + mHal.state.mallocPtr = NULL; } } @@ -153,15 +161,15 @@ void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) { void Allocation::uploadToTexture(const Context *rsc) { #ifndef ANDROID_RS_SERIALIZE - mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE; - GLenum type = mType->getElement()->getComponent().getGLType(); - GLenum format = mType->getElement()->getComponent().getGLFormat(); + mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE; + GLenum type = mHal.state.type->getElement()->getComponent().getGLType(); + GLenum format = mHal.state.type->getElement()->getComponent().getGLFormat(); if (!type || !format) { return; } - if (!mPtr) { + if (!mHal.state.mallocPtr) { return; } @@ -184,7 +192,7 @@ void Allocation::uploadToTexture(const Context *rsc) { upload2DTexture(isFirstUpload); - if (!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { + if (!(mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { freeScriptMemory(); } @@ -207,14 +215,14 @@ void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h) { #ifndef ANDROID_RS_SERIALIZE - GLenum type = mType->getElement()->getComponent().getGLType(); - GLenum format = mType->getElement()->getComponent().getGLFormat(); + GLenum type = mHal.state.type->getElement()->getComponent().getGLType(); + GLenum format = mHal.state.type->getElement()->getComponent().getGLFormat(); GLenum target = (GLenum)getGLTarget(); rsAssert(mTextureID); glBindTexture(target, mTextureID); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); GLenum t = GL_TEXTURE_2D; - if (mType->getDimFaces()) { + if (mHal.state.hasFaces) { t = gFaceOrder[face]; } glTexSubImage2D(t, lod, xoff, yoff, w, h, format, type, ptr); @@ -223,57 +231,57 @@ void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff, void Allocation::upload2DTexture(bool isFirstUpload) { #ifndef ANDROID_RS_SERIALIZE - GLenum type = mType->getElement()->getComponent().getGLType(); - GLenum format = mType->getElement()->getComponent().getGLFormat(); + GLenum type = mHal.state.type->getElement()->getComponent().getGLType(); + GLenum format = mHal.state.type->getElement()->getComponent().getGLFormat(); GLenum target = (GLenum)getGLTarget(); glBindTexture(target, mTextureID); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); uint32_t faceCount = 1; - if (mType->getDimFaces()) { + if (mHal.state.hasFaces) { faceCount = 6; } for (uint32_t face = 0; face < faceCount; face ++) { - for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) { - const uint8_t *p = (const uint8_t *)mPtr; - p += mType->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0); + for (uint32_t lod = 0; lod < mHal.state.type->getLODCount(); lod++) { + const uint8_t *p = (const uint8_t *)mHal.state.mallocPtr; + p += mHal.state.type->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0); GLenum t = GL_TEXTURE_2D; - if (mType->getDimFaces()) { + if (mHal.state.hasFaces) { t = gFaceOrder[face]; } if (isFirstUpload) { glTexImage2D(t, lod, format, - mType->getLODDimX(lod), mType->getLODDimY(lod), + mHal.state.type->getLODDimX(lod), mHal.state.type->getLODDimY(lod), 0, format, type, p); } else { glTexSubImage2D(t, lod, 0, 0, - mType->getLODDimX(lod), mType->getLODDimY(lod), + mHal.state.type->getLODDimX(lod), mHal.state.type->getLODDimY(lod), format, type, p); } } } - if (mMipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) { + if (mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) { glGenerateMipmap(target); } #endif //ANDROID_RS_SERIALIZE } void Allocation::deferedUploadToBufferObject(const Context *rsc) { - mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; + mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; mUploadDefered = true; } void Allocation::uploadToBufferObject(const Context *rsc) { #ifndef ANDROID_RS_SERIALIZE - rsAssert(!mType->getDimY()); - rsAssert(!mType->getDimZ()); + rsAssert(!mHal.state.type->getDimY()); + rsAssert(!mHal.state.type->getDimZ()); - mUsageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; + mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; if (!mBufferID) { glGenBuffers(1, &mBufferID); @@ -285,7 +293,7 @@ void Allocation::uploadToBufferObject(const Context *rsc) { } GLenum target = (GLenum)getGLTarget(); glBindBuffer(target, mBufferID); - glBufferData(target, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW); + glBufferData(target, mHal.state.type->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW); glBindBuffer(target, 0); rsc->checkError("Allocation::uploadToBufferObject"); #endif //ANDROID_RS_SERIALIZE @@ -298,23 +306,23 @@ void Allocation::uploadCheck(Context *rsc) { } void Allocation::read(void *data) { - memcpy(data, mPtr, mType->getSizeBytes()); + memcpy(data, mHal.state.mallocPtr, mHal.state.type->getSizeBytes()); } void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, const void *data, uint32_t sizeBytes) { - uint32_t eSize = mType->getElementSizeBytes(); - uint8_t * ptr = static_cast<uint8_t *>(mPtr); + uint32_t eSize = mHal.state.type->getElementSizeBytes(); + uint8_t * ptr = static_cast<uint8_t *>(mHal.state.mallocPtr); ptr += eSize * xoff; uint32_t size = count * eSize; if (size != sizeBytes) { LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes); - mType->dumpLOGV("type info"); + mHal.state.type->dumpLOGV("type info"); return; } - if (mType->getElement()->getHasReferences()) { + if (mHal.state.hasReferences) { incRefs(data, count); decRefs(ptr, count); } @@ -326,9 +334,9 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod, void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) { - uint32_t eSize = mType->getElementSizeBytes(); + uint32_t eSize = mHal.state.elementSizeBytes; uint32_t lineSize = eSize * w; - uint32_t destW = mType->getDimX(); + uint32_t destW = mHal.state.dimensionX; //LOGE("data2d %p, %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes); @@ -338,14 +346,14 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, return; } - if (mPtr) { + if (mHal.state.mallocPtr) { const uint8_t *src = static_cast<const uint8_t *>(data); - uint8_t *dst = static_cast<uint8_t *>(mPtr); - dst += mType->getLODFaceOffset(lod, face, xoff, yoff); + uint8_t *dst = static_cast<uint8_t *>(mHal.state.mallocPtr); + dst += mHal.state.type->getLODFaceOffset(lod, face, xoff, yoff); //LOGE(" %p %p %i ", dst, src, eSize); for (uint32_t line=yoff; line < (yoff+h); line++) { - if (mType->getElement()->getHasReferences()) { + if (mHal.state.hasReferences) { incRefs(src, w); decRefs(dst, w); } @@ -367,24 +375,24 @@ void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, void Allocation::elementData(Context *rsc, uint32_t x, const void *data, uint32_t cIdx, uint32_t sizeBytes) { - uint32_t eSize = mType->getElementSizeBytes(); - uint8_t * ptr = static_cast<uint8_t *>(mPtr); + uint32_t eSize = mHal.state.elementSizeBytes; + uint8_t * ptr = static_cast<uint8_t *>(mHal.state.mallocPtr); ptr += eSize * x; - if (cIdx >= mType->getElement()->getFieldCount()) { + if (cIdx >= mHal.state.type->getElement()->getFieldCount()) { LOGE("Error Allocation::subElementData component %i out of range.", cIdx); rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range."); return; } - if (x >= mType->getDimX()) { + if (x >= mHal.state.dimensionX) { LOGE("Error Allocation::subElementData X offset %i out of range.", x); rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); return; } - const Element * e = mType->getElement()->getField(cIdx); - ptr += mType->getElement()->getFieldOffsetBytes(cIdx); + const Element * e = mHal.state.type->getElement()->getField(cIdx); + ptr += mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); if (sizeBytes != e->getSizeBytes()) { LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes()); @@ -404,30 +412,30 @@ void Allocation::elementData(Context *rsc, uint32_t x, const void *data, void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y, const void *data, uint32_t cIdx, uint32_t sizeBytes) { - uint32_t eSize = mType->getElementSizeBytes(); - uint8_t * ptr = static_cast<uint8_t *>(mPtr); - ptr += eSize * (x + y * mType->getDimX()); + uint32_t eSize = mHal.state.elementSizeBytes; + uint8_t * ptr = static_cast<uint8_t *>(mHal.state.mallocPtr); + ptr += eSize * (x + y * mHal.state.dimensionX); - if (x >= mType->getDimX()) { + if (x >= mHal.state.dimensionX) { LOGE("Error Allocation::subElementData X offset %i out of range.", x); rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); return; } - if (y >= mType->getDimY()) { + if (y >= mHal.state.dimensionY) { LOGE("Error Allocation::subElementData X offset %i out of range.", x); rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); return; } - if (cIdx >= mType->getElement()->getFieldCount()) { + if (cIdx >= mHal.state.type->getElement()->getFieldCount()) { LOGE("Error Allocation::subElementData component %i out of range.", cIdx); rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range."); return; } - const Element * e = mType->getElement()->getField(cIdx); - ptr += mType->getElement()->getFieldOffsetBytes(cIdx); + const Element * e = mHal.state.type->getElement()->getField(cIdx); + ptr += mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); if (sizeBytes != e->getSizeBytes()) { LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes()); @@ -468,15 +476,15 @@ void Allocation::dumpLOGV(const char *prefix) const { String8 s(prefix); s.append(" type "); - if (mType.get()) { - mType->dumpLOGV(s.string()); + if (mHal.state.type.get()) { + mHal.state.type->dumpLOGV(s.string()); } LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i", - prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead); + prefix, mHal.state.mallocPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead); LOGV("%s allocation mUsageFlags=0x04%x, mMipmapControl=0x%04x, mTextureID=%i, mBufferID=%i", - prefix, mUsageFlags, mMipmapControl, mTextureID, mBufferID); + prefix, mHal.state.usageFlags, mHal.state.mipmapControl, mTextureID, mBufferID); } void Allocation::serialize(OStream *stream) const { @@ -488,13 +496,13 @@ void Allocation::serialize(OStream *stream) const { // First thing we need to serialize is the type object since it will be needed // to initialize the class - mType->serialize(stream); + mHal.state.type->serialize(stream); - uint32_t dataSize = mType->getSizeBytes(); + uint32_t dataSize = mHal.state.type->getSizeBytes(); // Write how much data we are storing stream->addU32(dataSize); // Now write the data - stream->addByteArray(mPtr, dataSize); + stream->addByteArray(mHal.state.mallocPtr, dataSize); } Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) { @@ -544,7 +552,7 @@ void Allocation::sendDirty() const { void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const { const uint8_t *p = static_cast<const uint8_t *>(ptr); - const Element *e = mType->getElement(); + const Element *e = mHal.state.type->getElement(); uint32_t stride = e->getSizeBytes(); p += stride * startOff; @@ -557,7 +565,7 @@ void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const { void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const { const uint8_t *p = static_cast<const uint8_t *>(ptr); - const Element *e = mType->getElement(); + const Element *e = mHal.state.type->getElement(); uint32_t stride = e->getSizeBytes(); p += stride * startOff; @@ -572,24 +580,26 @@ void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff } void Allocation::resize1D(Context *rsc, uint32_t dimX) { - Type *t = mType->cloneAndResize1D(rsc, dimX); + Type *t = mHal.state.type->cloneAndResize1D(rsc, dimX); - uint32_t oldDimX = mType->getDimX(); + uint32_t oldDimX = mHal.state.dimensionX; if (dimX == oldDimX) { return; } if (dimX < oldDimX) { - decRefs(mPtr, oldDimX - dimX, dimX); + decRefs(mHal.state.mallocPtr, oldDimX - dimX, dimX); } - mPtr = realloc(mPtr, t->getSizeBytes()); + mHal.state.mallocPtr = realloc(mHal.state.mallocPtr, t->getSizeBytes()); if (dimX > oldDimX) { - const Element *e = mType->getElement(); + const Element *e = mHal.state.type->getElement(); uint32_t stride = e->getSizeBytes(); - memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX)); + memset(((uint8_t *)mHal.state.mallocPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX)); } - mType.set(t); + + mHal.state.type.set(t); + updateCache(); } void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) { diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h index 4f5d5a8e351f..e63140c78666 100644 --- a/libs/rs/rsAllocation.h +++ b/libs/rs/rsAllocation.h @@ -29,10 +29,35 @@ class Allocation : public ObjectBase { // The graphics equilivent of malloc. The allocation contains a structure of elements. public: + struct Hal { + void * drv; + + struct State { + ObjectBaseRef<const Type> type; + void * mallocPtr; + + uint32_t usageFlags; + RsAllocationMipmapControl mipmapControl; + + // Cached fields from the Type and Element + // to prevent pointer chasing in critical loops. + uint32_t dimensionX; + uint32_t dimensionY; + uint32_t dimensionZ; + uint32_t elementSizeBytes; + bool hasMipmaps; + bool hasFaces; + bool hasReferences; + }; + State state; + }; + Hal mHal; + Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE); virtual ~Allocation(); + void updateCache(); void setCpuWritable(bool); void setGpuWritable(bool); @@ -41,8 +66,8 @@ public: bool fixAllocation(); - void * getPtr() const {return mPtr;} - const Type * getType() const {return mType.get();} + void * getPtr() const {return mHal.state.mallocPtr;} + const Type * getType() const {return mHal.state.type.get();} void syncAll(Context *rsc, RsAllocationUsageType src); @@ -88,13 +113,13 @@ public: virtual void uploadCheck(Context *rsc); bool getIsScript() const { - return (mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT) != 0; + return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) != 0; } bool getIsTexture() const { - return (mUsageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) != 0; + return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) != 0; } bool getIsBufferObject() const { - return (mUsageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) != 0; + return (mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) != 0; } void incRefs(const void *ptr, size_t ct, size_t startOff = 0) const; @@ -102,14 +127,11 @@ public: void sendDirty() const; bool getHasGraphicsMipmaps() const { - return mMipmapControl != RS_ALLOCATION_MIPMAP_NONE; + return mHal.state.mipmapControl != RS_ALLOCATION_MIPMAP_NONE; } protected: - ObjectBaseRef<const Type> mType; - void * mPtr; - Vector<const Program *> mToDirtyList; // Is we have a non-null user bitmap callback we do not own the bits and @@ -123,9 +145,6 @@ protected: bool mGpuWrite; bool mGpuRead; - uint32_t mUsageFlags; - RsAllocationMipmapControl mMipmapControl; - // more usage hint data from the application // which can be used by a driver to pick the best memory type. // Likely ignored for now diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index c63d183c7b59..c761c75e16b7 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -429,6 +429,8 @@ void Context::displayDebugStats() { mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA); uint32_t bufferLen = strlen(buffer); + ObjectBaseRef<Font> lastFont(getFont()); + setFont(NULL); float shadowCol = 0.1f; mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f); mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6); @@ -436,6 +438,7 @@ void Context::displayDebugStats() { mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f); mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7); + setFont(lastFont.get()); mStateFont.setFontColor(oldR, oldG, oldB, oldA); } @@ -551,56 +554,6 @@ void Context::destroyWorkerThreadResources() { mExit = true; } -void * Context::helperThreadProc(void *vrsc) { - Context *rsc = static_cast<Context *>(vrsc); - uint32_t idx = (uint32_t)android_atomic_inc(&rsc->mWorkers.mLaunchCount); - - //LOGV("RS helperThread starting %p idx=%i", rsc, idx); - - rsc->mWorkers.mLaunchSignals[idx].init(); - rsc->mWorkers.mNativeThreadId[idx] = gettid(); - -#if 0 - typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t; - cpu_set_t cpuset; - memset(&cpuset, 0, sizeof(cpuset)); - cpuset.bits[idx / 64] |= 1ULL << (idx % 64); - int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx], - sizeof(cpuset), &cpuset); - LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret)); -#endif - - setpriority(PRIO_PROCESS, rsc->mWorkers.mNativeThreadId[idx], rsc->mThreadPriority); - int status = pthread_setspecific(rsc->gThreadTLSKey, rsc->mTlsStruct); - if (status) { - LOGE("pthread_setspecific %i", status); - } - - while (!rsc->mExit) { - rsc->mWorkers.mLaunchSignals[idx].wait(); - if (rsc->mWorkers.mLaunchCallback) { - rsc->mWorkers.mLaunchCallback(rsc->mWorkers.mLaunchData, idx); - } - android_atomic_dec(&rsc->mWorkers.mRunningCount); - rsc->mWorkers.mCompleteSignal.set(); - } - - //LOGV("RS helperThread exited %p idx=%i", rsc, idx); - return NULL; -} - -void Context::launchThreads(WorkerCallback_t cbk, void *data) { - mWorkers.mLaunchData = data; - mWorkers.mLaunchCallback = cbk; - android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount); - for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { - mWorkers.mLaunchSignals[ct].set(); - } - while (android_atomic_acquire_load(&mWorkers.mRunningCount) != 0) { - mWorkers.mCompleteSignal.wait(); - } -} - void Context::setPriority(int32_t p) { // Note: If we put this in the proper "background" policy // the wallpapers can become completly unresponsive at times. @@ -617,9 +570,6 @@ void Context::setPriority(int32_t p) { } #else setpriority(PRIO_PROCESS, mNativeThreadId, p); - for (uint32_t ct=0; ct < mWorkers.mCount; ct++) { - setpriority(PRIO_PROCESS, mWorkers.mNativeThreadId[ct], p); - } #endif } @@ -685,15 +635,12 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) { timerInit(); timerSet(RS_TIMER_INTERNAL); - int cpu = sysconf(_SC_NPROCESSORS_ONLN); - LOGV("RS Launching thread(s), reported CPU count %i", cpu); - if (cpu < 2) cpu = 0; + if (!rsdHalInit(this, 0, 0)) { + LOGE("Hal init failed"); + return false; + } + mHal.funcs.setPriority(this, mThreadPriority); - mWorkers.mCount = (uint32_t)cpu; - mWorkers.mThreadId = (pthread_t *) calloc(mWorkers.mCount, sizeof(pthread_t)); - mWorkers.mNativeThreadId = (pid_t *) calloc(mWorkers.mCount, sizeof(pid_t)); - mWorkers.mLaunchSignals = new Signal[mWorkers.mCount]; - mWorkers.mLaunchCallback = NULL; status = pthread_create(&mThreadId, &threadAttr, threadProc, this); if (status) { LOGE("Failed to start rs context thread."); @@ -704,23 +651,10 @@ bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) { } if (mError != RS_ERROR_NONE) { + LOGE("Errors during thread init"); return false; } - mWorkers.mCompleteSignal.init(); - android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount); - android_atomic_release_store(0, &mWorkers.mLaunchCount); - for (uint32_t ct=0; ct < mWorkers.mCount; ct++) { - status = pthread_create(&mWorkers.mThreadId[ct], &threadAttr, helperThreadProc, this); - if (status) { - mWorkers.mCount = ct; - LOGE("Created fewer than expected number of RS threads."); - break; - } - } - while (android_atomic_acquire_load(&mWorkers.mRunningCount) != 0) { - usleep(100); - } pthread_attr_destroy(&threadAttr); return true; } @@ -737,17 +671,10 @@ Context::~Context() { mIO.shutdown(); int status = pthread_join(mThreadId, &res); - // Cleanup compute threads. - mWorkers.mLaunchData = NULL; - mWorkers.mLaunchCallback = NULL; - android_atomic_release_store(mWorkers.mCount, &mWorkers.mRunningCount); - for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { - mWorkers.mLaunchSignals[ct].set(); - } - for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { - status = pthread_join(mWorkers.mThreadId[ct], &res); + + if (mHal.funcs.shutdownDriver) { + mHal.funcs.shutdownDriver(this); } - rsAssert(android_atomic_acquire_load(&mWorkers.mRunningCount) == 0); // Global structure cleanup. pthread_mutex_lock(&gInitMutex); diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index 50f63df44401..72574a60a37d 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -22,6 +22,8 @@ #include "rsAllocation.h" #include "rsMesh.h" +#include "rs_hal.h" + #ifndef ANDROID_RS_SERIALIZE #include "rsMutex.h" #include "rsThreadIO.h" @@ -71,6 +73,13 @@ namespace renderscript { class Context { public: + struct Hal { + void * drv; + + RsdHalFunctions funcs; + }; + Hal mHal; + static Context * createContext(Device *, const RsSurfaceConfig *sc); ~Context(); @@ -81,11 +90,6 @@ public: // Library mutex (for providing thread-safe calls from the runtime) static pthread_mutex_t gLibMutex; - struct ScriptTLSStruct { - Context * mContext; - Script * mScript; - }; - class PushState { public: PushState(Context *); @@ -103,9 +107,6 @@ public: ScriptTLSStruct *mTlsStruct; RsSurfaceConfig mUserSurfaceConfig; - typedef void (*WorkerCallback_t)(void *usr, uint32_t idx); - - //StructuredAllocationContext mStateAllocation; ElementState mStateElement; TypeState mStateType; SamplerState mStateSampler; @@ -216,8 +217,6 @@ public: uint32_t getMaxVertexUniformVectors() const {return mGL.mMaxVertexUniformVectors;} uint32_t getMaxVertexAttributes() const {return mGL.mMaxVertexAttribs;} - void launchThreads(WorkerCallback_t cbk, void *data); - uint32_t getWorkerPoolSize() const {return (uint32_t)mWorkers.mCount;} uint32_t getDPI() const {return mDPI;} void setDPI(uint32_t dpi) {mDPI = dpi;} @@ -274,20 +273,6 @@ protected: pthread_t mThreadId; pid_t mNativeThreadId; - struct Workers { - volatile int mRunningCount; - volatile int mLaunchCount; - uint32_t mCount; - pthread_t *mThreadId; - pid_t *mNativeThreadId; - Signal mCompleteSignal; - - Signal *mLaunchSignals; - WorkerCallback_t mLaunchCallback; - void *mLaunchData; - }; - Workers mWorkers; - ObjectBaseRef<Script> mRootScript; ObjectBaseRef<ProgramFragment> mFragment; ObjectBaseRef<ProgramVertex> mVertex; diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp index afee2a314809..b84014fa31d4 100644 --- a/libs/rs/rsScript.cpp +++ b/libs/rs/rsScript.cpp @@ -21,6 +21,7 @@ using namespace android::renderscript; Script::Script(Context *rsc) : ObjectBase(rsc) { memset(&mEnviroment, 0, sizeof(mEnviroment)); + memset(&mHal, 0, sizeof(mHal)); mSlots = NULL; mTypes = NULL; @@ -37,48 +38,38 @@ Script::~Script() { } } -void Script::initSlots() { - if (mEnviroment.mFieldCount > 0) { - mSlots = new ObjectBaseRef<Allocation>[mEnviroment.mFieldCount]; - mTypes = new ObjectBaseRef<const Type>[mEnviroment.mFieldCount]; - } -} - void Script::setSlot(uint32_t slot, Allocation *a) { - if (slot >= mEnviroment.mFieldCount) { + //LOGE("setSlot %i %p", slot, a); + if (slot >= mHal.info.exportedVariableCount) { LOGE("Script::setSlot unable to set allocation, invalid slot index"); return; } mSlots[slot].set(a); + if (a != NULL) { + mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, a->getPtr()); + } else { + mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, NULL); + } } void Script::setVar(uint32_t slot, const void *val, uint32_t len) { - int32_t *destPtr = ((int32_t **)mEnviroment.mFieldAddress)[slot]; - if (destPtr) { - //LOGE("setVar f1 %f", ((const float *)destPtr)[0]); - //LOGE("setVar %p %i", destPtr, len); - memcpy(destPtr, val, len); - //LOGE("setVar f2 %f", ((const float *)destPtr)[0]); - } else { - //if (rsc->props.mLogScripts) { - LOGV("Calling setVar on slot = %i which is null", slot); - //} + //LOGE("setVar %i %p %i", slot, val, len); + if (slot >= mHal.info.exportedVariableCount) { + LOGE("Script::setVar unable to set allocation, invalid slot index"); + return; } + mRSC->mHal.funcs.script.setGlobalVar(mRSC, this, slot, (void *)val, len); } void Script::setVarObj(uint32_t slot, ObjectBase *val) { - ObjectBase **destPtr = ((ObjectBase ***)mEnviroment.mFieldAddress)[slot]; - - if (destPtr) { - if (val != NULL) { - val->incSysRef(); - } - if (*destPtr) { - (*destPtr)->decSysRef(); - } - *destPtr = val; + //LOGE("setVarObj %i %p", slot, val); + if (slot >= mHal.info.exportedVariableCount) { + LOGE("Script::setVarObj unable to set allocation, invalid slot index"); + return; } + //LOGE("setvarobj %i %p", slot, val); + mRSC->mHal.funcs.script.setGlobalObj(mRSC, this, slot, val); } namespace android { diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h index bad095bcfcdf..671fbe6746f4 100644 --- a/libs/rs/rsScript.h +++ b/libs/rs/rsScript.h @@ -31,6 +31,45 @@ class ProgramStore; class Script : public ObjectBase { public: + struct Hal { + void * drv; + + struct State { + ObjectBaseRef<const Type> type; + void * mallocPtr; + + uint32_t usageFlags; + RsAllocationMipmapControl mipmapControl; + + // Cached fields from the Type and Element + // to prevent pointer chasing in critical loops. + uint32_t dimensionX; + uint32_t dimensionY; + uint32_t dimensionZ; + uint32_t elementSizeBytes; + bool hasMipmaps; + bool hasFaces; + bool hasReferences; + }; + State state; + + struct DriverInfo { + int mVersionMajor; + int mVersionMinor; + + size_t exportedVariableCount; + size_t exportedFunctionCount; + size_t exportedPragmaCount; + char const **exportedPragmaKeyList; + char const **exportedPragmaValueList; + + int (* root)(); + bool isThreadable; + }; + DriverInfo info; + }; + Hal mHal; + typedef void (* InvokeFunc_t)(void); Script(Context *); @@ -45,16 +84,6 @@ public: ObjectBaseRef<ProgramFragment> mFragment; ObjectBaseRef<ProgramRaster> mRaster; ObjectBaseRef<ProgramStore> mFragmentStore; - - uint32_t mInvokeFunctionCount; - InvokeFunc_t *mInvokeFunctions; - uint32_t mFieldCount; - void ** mFieldAddress; - - char * mScriptText; - uint32_t mScriptTextLength; - - bool mIsThreadable; }; Enviroment_t mEnviroment; diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index e12926b0a641..d5c486b14d3d 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -19,9 +19,6 @@ #include "rsMatrix.h" #include "utils/Timers.h" #include "utils/StopWatch.h" -extern "C" { -#include "libdex/ZipArchive.h" -} #include <GLES/gl.h> #include <GLES/glext.h> @@ -36,94 +33,18 @@ using namespace android::renderscript; Context * rsc = tls->mContext; \ ScriptC * sc = (ScriptC *) tls->mScript -// Input: cacheDir -// Input: resName -// Input: extName -// -// Note: cacheFile = resName + extName -// -// Output: Returns cachePath == cacheDir + cacheFile -char *genCacheFileName(const char *cacheDir, - const char *resName, - const char *extName) { - char cachePath[512]; - char cacheFile[sizeof(cachePath)]; - const size_t kBufLen = sizeof(cachePath) - 1; - - cacheFile[0] = '\0'; - // Note: resName today is usually something like - // "/com.android.fountain:raw/fountain" - if (resName[0] != '/') { - // Get the absolute path of the raw/***.bc file. - - // Generate the absolute path. This doesn't do everything it - // should, e.g. if resName is "./out/whatever" it doesn't crunch - // the leading "./" out because this if-block is not triggered, - // but it'll make do. - // - if (getcwd(cacheFile, kBufLen) == NULL) { - LOGE("Can't get CWD while opening raw/***.bc file\n"); - return NULL; - } - // Append "/" at the end of cacheFile so far. - strncat(cacheFile, "/", kBufLen); - } - - // cacheFile = resName + extName - // - strncat(cacheFile, resName, kBufLen); - if (extName != NULL) { - // TODO(srhines): strncat() is a bit dangerous - strncat(cacheFile, extName, kBufLen); - } - - // Turn the path into a flat filename by replacing - // any slashes after the first one with '@' characters. - char *cp = cacheFile + 1; - while (*cp != '\0') { - if (*cp == '/') { - *cp = '@'; - } - cp++; - } - - // Tack on the file name for the actual cache file path. - strncpy(cachePath, cacheDir, kBufLen); - strncat(cachePath, cacheFile, kBufLen); - - LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath); - return strdup(cachePath); -} - ScriptC::ScriptC(Context *rsc) : Script(rsc) { - mBccScript = NULL; - memset(&mProgram, 0, sizeof(mProgram)); } ScriptC::~ScriptC() { - if (mBccScript) { - if (mProgram.mObjectSlotList) { - for (size_t ct=0; ct < mProgram.mObjectSlotCount; ct++) { - setVarObj(mProgram.mObjectSlotList[ct], NULL); - } - delete [] mProgram.mObjectSlotList; - mProgram.mObjectSlotList = NULL; - mProgram.mObjectSlotCount = 0; - } - - - LOGD(">>>> ~ScriptC bccDisposeScript(%p)", mBccScript); - bccDisposeScript(mBccScript); - } - free(mEnviroment.mScriptText); - mEnviroment.mScriptText = NULL; + mRSC->mHal.funcs.script.destroy(mRSC, this); } void ScriptC::setupScript(Context *rsc) { mEnviroment.mStartTimeMillis = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); - for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) { + for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) { if (mSlots[ct].get() && !mTypes[ct].get()) { mTypes[ct].set(mSlots[ct]->getType()); } @@ -134,27 +55,17 @@ void ScriptC::setupScript(Context *rsc) { if (mSlots[ct].get()) { ptr = mSlots[ct]->getPtr(); } - void **dest = ((void ***)mEnviroment.mFieldAddress)[ct]; - if (rsc->props.mLogScripts) { - if (mSlots[ct].get() != NULL) { - LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=%p", rsc, ct, dest, ptr, mSlots[ct]->getType()); - } else { - LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=null", rsc, ct, dest, ptr); - } - } - - if (dest) { - *dest = ptr; - } + rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, ptr); } } const Allocation *ScriptC::ptrToAllocation(const void *ptr) const { + //LOGE("ptr to alloc %p", ptr); if (!ptr) { return NULL; } - for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) { + for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) { if (!mSlots[ct].get()) continue; if (mSlots[ct]->getPtr() == ptr) { @@ -165,15 +76,6 @@ const Allocation *ScriptC::ptrToAllocation(const void *ptr) const { return NULL; } -Script * ScriptC::setTLS(Script *sc) { - Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *) - pthread_getspecific(Context::gThreadTLSKey); - rsAssert(tls); - Script *old = tls->mScript; - tls->mScript = sc; - return old; -} - void ScriptC::setupGLState(Context *rsc) { if (mEnviroment.mFragmentStore.get()) { rsc->setProgramStore(mEnviroment.mFragmentStore.get()); @@ -190,7 +92,7 @@ void ScriptC::setupGLState(Context *rsc) { } uint32_t ScriptC::run(Context *rsc) { - if (mProgram.mRoot == NULL) { + if (mHal.info.root == NULL) { rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script"); return 0; } @@ -199,235 +101,45 @@ uint32_t ScriptC::run(Context *rsc) { setupScript(rsc); uint32_t ret = 0; - Script * oldTLS = setTLS(this); if (rsc->props.mLogScripts) { - LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mProgram.mRoot); + LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mHal.info.root); } - ret = mProgram.mRoot(); + ret = rsc->mHal.funcs.script.invokeRoot(rsc, this); if (rsc->props.mLogScripts) { LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret); } - setTLS(oldTLS); return ret; } -typedef struct { - Context *rsc; - ScriptC *script; - const Allocation * ain; - Allocation * aout; - const void * usr; - - uint32_t mSliceSize; - volatile int mSliceNum; - - const uint8_t *ptrIn; - uint32_t eStrideIn; - uint8_t *ptrOut; - uint32_t eStrideOut; - - uint32_t xStart; - uint32_t xEnd; - uint32_t yStart; - uint32_t yEnd; - uint32_t zStart; - uint32_t zEnd; - uint32_t arrayStart; - uint32_t arrayEnd; - - uint32_t dimX; - uint32_t dimY; - uint32_t dimZ; - uint32_t dimArray; -} MTLaunchStruct; -typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t); - -static void wc_xy(void *usr, uint32_t idx) { - MTLaunchStruct *mtls = (MTLaunchStruct *)usr; - - while (1) { - uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); - uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize; - uint32_t yEnd = yStart + mtls->mSliceSize; - yEnd = rsMin(yEnd, mtls->yEnd); - if (yEnd <= yStart) { - return; - } - - //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd); - //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut); - for (uint32_t y = yStart; y < yEnd; y++) { - uint32_t offset = mtls->dimX * y; - uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset); - const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset); - - for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) { - ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0); - xPtrIn += mtls->eStrideIn; - xPtrOut += mtls->eStrideOut; - } - } - } -} - -static void wc_x(void *usr, uint32_t idx) { - MTLaunchStruct *mtls = (MTLaunchStruct *)usr; - - while (1) { - uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); - uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize; - uint32_t xEnd = xStart + mtls->mSliceSize; - xEnd = rsMin(xEnd, mtls->xEnd); - if (xEnd <= xStart) { - return; - } - - //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd); - //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut); - uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart); - const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart); - for (uint32_t x = xStart; x < xEnd; x++) { - ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0); - xPtrIn += mtls->eStrideIn; - xPtrOut += mtls->eStrideOut; - } - } -} void ScriptC::runForEach(Context *rsc, const Allocation * ain, Allocation * aout, const void * usr, const RsScriptCall *sc) { - MTLaunchStruct mtls; - memset(&mtls, 0, sizeof(mtls)); - Context::PushState ps(rsc); - - if (ain) { - mtls.dimX = ain->getType()->getDimX(); - mtls.dimY = ain->getType()->getDimY(); - mtls.dimZ = ain->getType()->getDimZ(); - //mtls.dimArray = ain->getType()->getDimArray(); - } else if (aout) { - mtls.dimX = aout->getType()->getDimX(); - mtls.dimY = aout->getType()->getDimY(); - mtls.dimZ = aout->getType()->getDimZ(); - //mtls.dimArray = aout->getType()->getDimArray(); - } else { - rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); - return; - } - - if (!sc || (sc->xEnd == 0)) { - mtls.xEnd = mtls.dimX; - } else { - rsAssert(sc->xStart < mtls.dimX); - rsAssert(sc->xEnd <= mtls.dimX); - rsAssert(sc->xStart < sc->xEnd); - mtls.xStart = rsMin(mtls.dimX, sc->xStart); - mtls.xEnd = rsMin(mtls.dimX, sc->xEnd); - if (mtls.xStart >= mtls.xEnd) return; - } - - if (!sc || (sc->yEnd == 0)) { - mtls.yEnd = mtls.dimY; - } else { - rsAssert(sc->yStart < mtls.dimY); - rsAssert(sc->yEnd <= mtls.dimY); - rsAssert(sc->yStart < sc->yEnd); - mtls.yStart = rsMin(mtls.dimY, sc->yStart); - mtls.yEnd = rsMin(mtls.dimY, sc->yEnd); - if (mtls.yStart >= mtls.yEnd) return; - } - - mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd); - mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd); - mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd); - mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd); - rsAssert(ain->getType()->getDimZ() == 0); + Context::PushState ps(rsc); setupGLState(rsc); setupScript(rsc); - Script * oldTLS = setTLS(this); - - mtls.rsc = rsc; - mtls.ain = ain; - mtls.aout = aout; - mtls.script = this; - mtls.usr = usr; - mtls.mSliceSize = 10; - mtls.mSliceNum = 0; - - mtls.ptrIn = NULL; - mtls.eStrideIn = 0; - if (ain) { - mtls.ptrIn = (const uint8_t *)ain->getPtr(); - mtls.eStrideIn = ain->getType()->getElementSizeBytes(); - } - - mtls.ptrOut = NULL; - mtls.eStrideOut = 0; - if (aout) { - mtls.ptrOut = (uint8_t *)aout->getPtr(); - mtls.eStrideOut = aout->getType()->getElementSizeBytes(); - } - - if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable) { - if (mtls.dimY > 1) { - rsc->launchThreads(wc_xy, &mtls); - } else { - rsc->launchThreads(wc_x, &mtls); - } - - //LOGE("launch 1"); - } else { - //LOGE("launch 3"); - for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) { - for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) { - for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) { - uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar + - mtls.dimX * mtls.dimY * z + - mtls.dimX * y; - uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset); - const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset); - - for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) { - ((rs_t)mProgram.mRoot) (xPtrIn, xPtrOut, usr, x, y, z, ar); - xPtrIn += mtls.eStrideIn; - xPtrOut += mtls.eStrideOut; - } - } - } - } - } - - setTLS(oldTLS); + rsc->mHal.funcs.script.invokeForEach(rsc, this, ain, aout, usr, 0, sc); } void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) { - if ((slot >= mEnviroment.mInvokeFunctionCount) || - (mEnviroment.mInvokeFunctions[slot] == NULL)) { + if (slot >= mHal.info.exportedFunctionCount) { rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script"); return; } setupScript(rsc); - Script * oldTLS = setTLS(this); if (rsc->props.mLogScripts) { - LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, mEnviroment.mInvokeFunctions[slot]); - } - ((void (*)(const void *, uint32_t)) - mEnviroment.mInvokeFunctions[slot])(data, len); - if (rsc->props.mLogScripts) { - LOGV("%p ScriptC::Invoke complete", rsc); + LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, this); } - - setTLS(oldTLS); + rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len); } ScriptCState::ScriptCState() { @@ -440,9 +152,9 @@ static void* symbolLookup(void* pContext, char const* name) { const ScriptCState::SymbolTable_t *sym; ScriptC *s = (ScriptC *)pContext; if (!strcmp(name, "__isThreadable")) { - return (void*) s->mEnviroment.mIsThreadable; + return (void*) s->mHal.info.isThreadable; } else if (!strcmp(name, "__clearThreadable")) { - s->mEnviroment.mIsThreadable = false; + s->mHal.info.isThreadable = false; return NULL; } sym = ScriptCState::lookupSymbol(name); @@ -453,7 +165,7 @@ static void* symbolLookup(void* pContext, char const* name) { sym = ScriptCState::lookupSymbolGL(name); } if (sym) { - s->mEnviroment.mIsThreadable &= sym->threadable; + s->mHal.info.isThreadable &= sym->threadable; return sym->mPtr; } LOGE("ScriptC sym lookup failed for %s", name); @@ -465,144 +177,86 @@ extern const char rs_runtime_lib_bc[]; extern unsigned rs_runtime_lib_bc_size; #endif -bool ScriptCState::runCompiler(Context *rsc, - ScriptC *s, - const char *resName, - const char *cacheDir) { - s->mBccScript = bccCreateScript(); +bool ScriptC::runCompiler(Context *rsc, + const char *resName, + const char *cacheDir, + const uint8_t *bitcode, + size_t bitcodeLen) { - s->mEnviroment.mIsThreadable = true; + //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen); - if (bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s) != 0) { - LOGE("bcc: FAILS to register symbol callback"); - return false; - } + rsc->mHal.funcs.script.scriptInit(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0, symbolLookup); - if (bccReadBC(s->mBccScript, - resName, - s->mEnviroment.mScriptText, - s->mEnviroment.mScriptTextLength, 0) != 0) { - LOGE("bcc: FAILS to read bitcode"); - return false; - } + mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); + mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); + mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore()); + mEnviroment.mRaster.set(rsc->getDefaultProgramRaster()); -#if 1 - if (bccLinkFile(s->mBccScript, "/system/lib/libclcore.bc", 0) != 0) { - LOGE("bcc: FAILS to link bitcode"); - return false; - } -#endif - char *cachePath = genCacheFileName(cacheDir, resName, ".oBCC"); - - if (bccPrepareExecutable(s->mBccScript, cachePath, 0) != 0) { - LOGE("bcc: FAILS to prepare executable"); - return false; - } + rsc->mHal.funcs.script.invokeInit(rsc, this); - free(cachePath); - - s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root")); - s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init")); - - if (s->mProgram.mInit) { - s->mProgram.mInit(); - } - - s->mEnviroment.mInvokeFunctionCount = bccGetExportFuncCount(s->mBccScript); - if (s->mEnviroment.mInvokeFunctionCount <= 0) - s->mEnviroment.mInvokeFunctions = NULL; - else { - s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t*) calloc(s->mEnviroment.mInvokeFunctionCount, sizeof(Script::InvokeFunc_t)); - bccGetExportFuncList(s->mBccScript, s->mEnviroment.mInvokeFunctionCount, (void **) s->mEnviroment.mInvokeFunctions); - } - - s->mEnviroment.mFieldCount = bccGetExportVarCount(s->mBccScript); - if (s->mEnviroment.mFieldCount <= 0) - s->mEnviroment.mFieldAddress = NULL; - else { - s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *)); - bccGetExportVarList(s->mBccScript, s->mEnviroment.mFieldCount, (void **) s->mEnviroment.mFieldAddress); - s->initSlots(); - } - - s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); - s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); - s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore()); - s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster()); - - const static int pragmaMax = 16; - size_t pragmaCount = bccGetPragmaCount(s->mBccScript); - char const *keys[pragmaMax]; - char const *values[pragmaMax]; - bccGetPragmaList(s->mBccScript, pragmaMax, keys, values); - - for (size_t i=0; i < pragmaCount; ++i) { + for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) { + const char * key = mHal.info.exportedPragmaKeyList[i]; + const char * value = mHal.info.exportedPragmaValueList[i]; //LOGE("pragma %s %s", keys[i], values[i]); - if (!strcmp(keys[i], "version")) { - if (!strcmp(values[i], "1")) { + if (!strcmp(key, "version")) { + if (!strcmp(value, "1")) { continue; } - LOGE("Invalid version pragma value: %s\n", values[i]); + LOGE("Invalid version pragma value: %s\n", value); return false; } - if (!strcmp(keys[i], "stateVertex")) { - if (!strcmp(values[i], "default")) { + if (!strcmp(key, "stateVertex")) { + if (!strcmp(value, "default")) { continue; } - if (!strcmp(values[i], "parent")) { - s->mEnviroment.mVertex.clear(); + if (!strcmp(value, "parent")) { + mEnviroment.mVertex.clear(); continue; } - LOGE("Unrecognized value %s passed to stateVertex", values[i]); + LOGE("Unrecognized value %s passed to stateVertex", value); return false; } - if (!strcmp(keys[i], "stateRaster")) { - if (!strcmp(values[i], "default")) { + if (!strcmp(key, "stateRaster")) { + if (!strcmp(value, "default")) { continue; } - if (!strcmp(values[i], "parent")) { - s->mEnviroment.mRaster.clear(); + if (!strcmp(value, "parent")) { + mEnviroment.mRaster.clear(); continue; } - LOGE("Unrecognized value %s passed to stateRaster", values[i]); + LOGE("Unrecognized value %s passed to stateRaster", value); return false; } - if (!strcmp(keys[i], "stateFragment")) { - if (!strcmp(values[i], "default")) { + if (!strcmp(key, "stateFragment")) { + if (!strcmp(value, "default")) { continue; } - if (!strcmp(values[i], "parent")) { - s->mEnviroment.mFragment.clear(); + if (!strcmp(value, "parent")) { + mEnviroment.mFragment.clear(); continue; } - LOGE("Unrecognized value %s passed to stateFragment", values[i]); + LOGE("Unrecognized value %s passed to stateFragment", value); return false; } - if (!strcmp(keys[i], "stateStore")) { - if (!strcmp(values[i], "default")) { + if (!strcmp(key, "stateStore")) { + if (!strcmp(value, "default")) { continue; } - if (!strcmp(values[i], "parent")) { - s->mEnviroment.mFragmentStore.clear(); + if (!strcmp(value, "parent")) { + mEnviroment.mFragmentStore.clear(); continue; } - LOGE("Unrecognized value %s passed to stateStore", values[i]); + LOGE("Unrecognized value %s passed to stateStore", value); return false; } } - size_t objectSlotCount = bccGetObjectSlotCount(s->mBccScript); - uint32_t *objectSlots = NULL; - if (objectSlotCount) { - objectSlots = new uint32_t[objectSlotCount]; - bccGetObjectSlotList(s->mBccScript, objectSlotCount, objectSlots); - s->mProgram.mObjectSlotList = objectSlots; - s->mProgram.mObjectSlotCount = objectSlotCount; - } + mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount]; + mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount]; return true; } @@ -610,39 +264,19 @@ bool ScriptCState::runCompiler(Context *rsc, namespace android { namespace renderscript { -void rsi_ScriptCBegin(Context * rsc) { -} - -void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) { - ScriptCState *ss = &rsc->mScriptC; - - char *t = (char *)malloc(len + 1); - memcpy(t, text, len); - t[len] = 0; - ss->mScriptText = t; - ss->mScriptLen = len; -} - - RsScript rsi_ScriptCCreate(Context *rsc, - const char *packageName /* deprecated */, - const char *resName, - const char *cacheDir) + const char *resName, const char *cacheDir, + const char *text, uint32_t len) { - ScriptCState *ss = &rsc->mScriptC; - ScriptC *s = new ScriptC(rsc); - s->mEnviroment.mScriptText = ss->mScriptText; - s->mEnviroment.mScriptTextLength = ss->mScriptLen; - ss->mScriptText = NULL; - ss->mScriptLen = 0; - s->incUserRef(); - if (!ss->runCompiler(rsc, s, resName, cacheDir)) { + if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, len)) { // Error during compile, destroy s and return null. delete s; return NULL; } + + s->incUserRef(); return s; } diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h index 2c74b5b3ef4e..2edeb9b42c35 100644 --- a/libs/rs/rsScriptC.h +++ b/libs/rs/rsScriptC.h @@ -21,7 +21,6 @@ #include "RenderScriptEnv.h" -struct BCCOpaqueScript; // --------------------------------------------------------------------------- namespace android { @@ -36,21 +35,6 @@ public: ScriptC(Context *); virtual ~ScriptC(); - struct Program_t { - int mVersionMajor; - int mVersionMinor; - - RunScript_t mRoot; - VoidFunc_t mInit; - - uint32_t * mObjectSlotList; - uint32_t mObjectSlotCount; - }; - - - Program_t mProgram; - - BCCOpaqueScript *mBccScript; const Allocation *ptrToAllocation(const void *) const; @@ -69,7 +53,10 @@ public: virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_SCRIPT_C; } static Type *createFromStream(Context *rsc, IStream *stream) { return NULL; } -protected: + bool runCompiler(Context *rsc, const char *resName, const char *cacheDir, + const uint8_t *bitcode, size_t bitcodeLen); + +//protected: void setupScript(Context *); void setupGLState(Context *); Script * setTLS(Script *); @@ -83,8 +70,6 @@ public: char * mScriptText; size_t mScriptLen; - bool runCompiler(Context *rsc, ScriptC *s, const char *resName, const char *cacheDir); - struct SymbolTable_t { const char * mName; void * mPtr; diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp index 23230a630809..4e8cbdcc60be 100644 --- a/libs/rs/rsScriptC_Lib.cpp +++ b/libs/rs/rsScriptC_Lib.cpp @@ -25,8 +25,8 @@ using namespace android; using namespace android::renderscript; -#define GET_TLS() Context::ScriptTLSStruct * tls = \ - (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ +#define GET_TLS() ScriptTLSStruct * tls = \ + (ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ Context * rsc = tls->mContext; \ ScriptC * sc = (ScriptC *) tls->mScript @@ -141,90 +141,74 @@ static float SC_getDt() { // ////////////////////////////////////////////////////////////////////////////// -static uint32_t SC_allocGetDimX(RsAllocation va) { - const Allocation *a = static_cast<const Allocation *>(va); +static uint32_t SC_allocGetDimX(Allocation *a) { CHECK_OBJ(a); - //LOGE("SC_allocGetDimX a=%p type=%p", a, a->getType()); - return a->getType()->getDimX(); + return a->mHal.state.dimensionX; } -static uint32_t SC_allocGetDimY(RsAllocation va) { - const Allocation *a = static_cast<const Allocation *>(va); +static uint32_t SC_allocGetDimY(Allocation *a) { CHECK_OBJ(a); - return a->getType()->getDimY(); + return a->mHal.state.dimensionY; } -static uint32_t SC_allocGetDimZ(RsAllocation va) { - const Allocation *a = static_cast<const Allocation *>(va); +static uint32_t SC_allocGetDimZ(Allocation *a) { CHECK_OBJ(a); - return a->getType()->getDimZ(); + return a->mHal.state.dimensionZ; } -static uint32_t SC_allocGetDimLOD(RsAllocation va) { - const Allocation *a = static_cast<const Allocation *>(va); +static uint32_t SC_allocGetDimLOD(Allocation *a) { CHECK_OBJ(a); - return a->getType()->getDimLOD(); + return a->mHal.state.hasMipmaps; } -static uint32_t SC_allocGetDimFaces(RsAllocation va) { - const Allocation *a = static_cast<const Allocation *>(va); +static uint32_t SC_allocGetDimFaces(Allocation *a) { CHECK_OBJ(a); - return a->getType()->getDimFaces(); + return a->mHal.state.hasFaces; } -static const void * SC_getElementAtX(RsAllocation va, uint32_t x) { - const Allocation *a = static_cast<const Allocation *>(va); +static const void * SC_getElementAtX(Allocation *a, uint32_t x) { CHECK_OBJ(a); - const Type *t = a->getType(); - CHECK_OBJ(t); const uint8_t *p = (const uint8_t *)a->getPtr(); - return &p[t->getElementSizeBytes() * x]; + return &p[a->mHal.state.elementSizeBytes * x]; } -static const void * SC_getElementAtXY(RsAllocation va, uint32_t x, uint32_t y) { - const Allocation *a = static_cast<const Allocation *>(va); +static const void * SC_getElementAtXY(Allocation *a, uint32_t x, uint32_t y) { CHECK_OBJ(a); - const Type *t = a->getType(); - CHECK_OBJ(t); const uint8_t *p = (const uint8_t *)a->getPtr(); - return &p[t->getElementSizeBytes() * (x + y*t->getDimX())]; + return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX)]; } -static const void * SC_getElementAtXYZ(RsAllocation va, uint32_t x, uint32_t y, uint32_t z) { - const Allocation *a = static_cast<const Allocation *>(va); +static const void * SC_getElementAtXYZ(Allocation *a, uint32_t x, uint32_t y, uint32_t z) { CHECK_OBJ(a); - const Type *t = a->getType(); - CHECK_OBJ(t); const uint8_t *p = (const uint8_t *)a->getPtr(); - return &p[t->getElementSizeBytes() * (x + y*t->getDimX())]; + return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX + + z * a->mHal.state.dimensionX * a->mHal.state.dimensionY)]; } -static void SC_setObject(void **vdst, void * vsrc) { - //LOGE("SC_setObject %p,%p %p", vdst, *vdst, vsrc); - if (vsrc) { - CHECK_OBJ(vsrc); - static_cast<ObjectBase *>(vsrc)->incSysRef(); +void android::renderscript::rsiSetObject(ObjectBase **dst, ObjectBase * src) { + //LOGE("rsiSetObject %p,%p %p", vdst, *vdst, vsrc); + if (src) { + CHECK_OBJ(src); + src->incSysRef(); } - if (vdst[0]) { - CHECK_OBJ(vdst[0]); - static_cast<ObjectBase *>(vdst[0])->decSysRef(); + if (dst[0]) { + CHECK_OBJ(dst[0]); + dst[0]->decSysRef(); } - *vdst = vsrc; - //LOGE("SC_setObject *"); + *dst = src; } -static void SC_clearObject(void **vdst) { - //LOGE("SC_clearObject %p,%p", vdst, *vdst); - if (vdst[0]) { - CHECK_OBJ(vdst[0]); - static_cast<ObjectBase *>(vdst[0])->decSysRef(); +void android::renderscript::rsiClearObject(ObjectBase **dst) { + //LOGE("rsiClearObject %p,%p", vdst, *vdst); + if (dst[0]) { + CHECK_OBJ(dst[0]); + dst[0]->decSysRef(); } - *vdst = NULL; - //LOGE("SC_clearObject *"); + *dst = NULL; } -static bool SC_isObject(RsAllocation vsrc) { - return vsrc != NULL; +bool android::renderscript::rsiIsObject(const ObjectBase *src) { + return src != NULL; } static void SC_debugF(const char *s, float f) { @@ -873,49 +857,49 @@ static ScriptCState::SymbolTable_t gSyms[] = { { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true }, { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true }, - { "_Z11rsSetObjectP10rs_elementS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP10rs_element", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject10rs_element", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP10rs_elementS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP10rs_element", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject10rs_element", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP7rs_typeS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP7rs_type", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject7rs_type", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP7rs_typeS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP7rs_type", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject7rs_type", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP13rs_allocationS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP13rs_allocation", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject13rs_allocation", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP13rs_allocationS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP13rs_allocation", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject13rs_allocation", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP10rs_samplerS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP10rs_sampler", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject10rs_sampler", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP10rs_samplerS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP10rs_sampler", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject10rs_sampler", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP9rs_scriptS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP9rs_script", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject9rs_script", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP9rs_scriptS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP9rs_script", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject9rs_script", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject7rs_mesh", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP7rs_meshS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP7rs_mesh", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject7rs_mesh", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP19rs_program_fragment", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject19rs_program_fragment", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP19rs_program_fragment", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject19rs_program_fragment", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP17rs_program_vertex", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject17rs_program_vertex", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP17rs_program_vertex", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject17rs_program_vertex", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP17rs_program_raster", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject17rs_program_raster", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP17rs_program_raster", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject17rs_program_raster", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP16rs_program_store", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject16rs_program_store", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP16rs_program_store", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject16rs_program_store", (void *)&rsiIsObject, true }, - { "_Z11rsSetObjectP7rs_fontS_", (void *)&SC_setObject, true }, - { "_Z13rsClearObjectP7rs_font", (void *)&SC_clearObject, true }, - { "_Z10rsIsObject7rs_font", (void *)&SC_isObject, true }, + { "_Z11rsSetObjectP7rs_fontS_", (void *)&rsiSetObject, true }, + { "_Z13rsClearObjectP7rs_font", (void *)&rsiClearObject, true }, + { "_Z10rsIsObject7rs_font", (void *)&rsiIsObject, true }, { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty, true }, @@ -1000,7 +984,7 @@ static ScriptCState::SymbolTable_t gSyms[] = { { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_2x2, true }, { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false }, - //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, true }, + //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, false }, //////////////////////////////////////////////////////////////////// @@ -1021,3 +1005,4 @@ const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) } return NULL; } + diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp index 15426bc33f9f..4047049a8ae5 100644 --- a/libs/rs/rsScriptC_LibGL.cpp +++ b/libs/rs/rsScriptC_LibGL.cpp @@ -32,8 +32,8 @@ using namespace android; using namespace android::renderscript; -#define GET_TLS() Context::ScriptTLSStruct * tls = \ - (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ +#define GET_TLS() ScriptTLSStruct * tls = \ + (ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ Context * rsc = tls->mContext; \ ScriptC * sc = (ScriptC *) tls->mScript diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h new file mode 100644 index 000000000000..17983ce76484 --- /dev/null +++ b/libs/rs/rs_hal.h @@ -0,0 +1,104 @@ +/* + * 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 RS_HAL_H +#define RS_HAL_H + +#include <RenderScriptDefines.h> + +namespace android { +namespace renderscript { + +class Context; +class ObjectBase; +class Element; +class Type; +class Allocation; +class Script; +class ScriptC; + + +typedef void *(*RsHalSymbolLookupFunc)(void *usrptr, char const *symbolName); + +typedef struct ScriptTLSStructRec { + Context * mContext; + Script * mScript; +} ScriptTLSStruct; + + +/** + * Script management functions + */ +typedef struct { + void (*shutdownDriver)(Context *); + void (*getVersion)(unsigned int *major, unsigned int *minor); + void (*setPriority)(const Context *, int32_t priority); + + + + struct { + bool (*scriptInit)(const Context *rsc, ScriptC *s, + char const *resName, + char const *cacheDir, + uint8_t const *bitcode, + size_t bitcodeSize, + uint32_t flags, + RsHalSymbolLookupFunc lookupFunc); + + void (*invokeFunction)(const Context *rsc, Script *s, + uint32_t slot, + const void *params, + size_t paramLength); + int (*invokeRoot)(const Context *rsc, Script *s); + void (*invokeForEach)(const Context *rsc, + Script *s, + const Allocation * ain, + Allocation * aout, + const void * usr, + uint32_t usrLen, + const RsScriptCall *sc); + void (*invokeInit)(const Context *rsc, Script *s); + + void (*setGlobalVar)(const Context *rsc, const Script *s, + uint32_t slot, + void *data, + size_t dataLength); + void (*setGlobalBind)(const Context *rsc, const Script *s, + uint32_t slot, + void *data); + void (*setGlobalObj)(const Context *rsc, const Script *s, + uint32_t slot, + ObjectBase *data); + + void (*destroy)(const Context *rsc, Script *s); + } script; + + + +} RsdHalFunctions; + +void rsiSetObject(ObjectBase **vdst, ObjectBase * vsrc); +void rsiClearObject(ObjectBase **vdst); +bool rsiIsObject(const ObjectBase *vdst); + +} +} + + +bool rsdHalInit(android::renderscript::Context *, uint32_t version_major, uint32_t version_minor); + +#endif + diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk index 4a0faf06a12c..267e3edf44e3 100644 --- a/libs/surfaceflinger_client/Android.mk +++ b/libs/surfaceflinger_client/Android.mk @@ -1,22 +1,9 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= \ - ISurfaceComposer.cpp \ - ISurface.cpp \ - ISurfaceComposerClient.cpp \ - IGraphicBufferAlloc.cpp \ - LayerState.cpp \ - SharedBufferStack.cpp \ - Surface.cpp \ - SurfaceComposerClient.cpp +LOCAL_SRC_FILES:= -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libbinder \ - libhardware \ - libui +LOCAL_SHARED_LIBRARIES := LOCAL_MODULE:= libsurfaceflinger_client diff --git a/libs/surfaceflinger_client/tests/Android.mk b/libs/surfaceflinger_client/tests/Android.mk deleted file mode 100644 index 212b8e75919a..000000000000 --- a/libs/surfaceflinger_client/tests/Android.mk +++ /dev/null @@ -1,53 +0,0 @@ -# Build the unit tests. -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -ifneq ($(TARGET_SIMULATOR),true) - -# Build the unit tests. -test_src_files := \ - Surface_test.cpp \ - -shared_libraries := \ - libcutils \ - libutils \ - libbinder \ - libsurfaceflinger_client \ - libstlport \ - -static_libraries := \ - libgtest \ - libgtest_main \ - -c_includes := \ - bionic \ - bionic/libstdc++/include \ - external/gtest/include \ - external/stlport/stlport \ - -module_tags := tests - -$(foreach file,$(test_src_files), \ - $(eval include $(CLEAR_VARS)) \ - $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ - $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ - $(eval LOCAL_C_INCLUDES := $(c_includes)) \ - $(eval LOCAL_SRC_FILES := $(file)) \ - $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ - $(eval LOCAL_MODULE_TAGS := $(module_tags)) \ - $(eval include $(BUILD_EXECUTABLE)) \ -) - -# Build the manual test programs. -include $(call all-subdir-makefiles) - -endif - -# Include subdirectory makefiles -# ============================================================ - -# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework -# team really wants is to build the stuff defined by this makefile. -ifeq (,$(ONE_SHOT_MAKEFILE)) -include $(call first-makefiles-under,$(LOCAL_PATH)) -endif diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk b/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk deleted file mode 100644 index d3dfe042850f..000000000000 --- a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk +++ /dev/null @@ -1,17 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - SharedBufferStackTest.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libui \ - libsurfaceflinger_client - -LOCAL_MODULE:= test-sharedbufferstack - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp deleted file mode 100644 index 7ef59269bade..000000000000 --- a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#undef NDEBUG - -#include <assert.h> -#include <cutils/memory.h> -#include <cutils/log.h> -#include <utils/Errors.h> -#include <private/surfaceflinger/SharedBufferStack.h> - -using namespace android; - -void log(const char* prefix, int *b, size_t num); -void test0(SharedBufferServer& s, SharedBufferClient& c, size_t num, int* list); - -// ---------------------------------------------------------------------------- - -int main(int argc, char** argv) -{ - SharedClient client; - sp<SharedBufferServer> ps(new SharedBufferServer(&client, 0, 4, 0)); - SharedBufferServer& s(*ps); - SharedBufferClient c(&client, 0, 4, 0); - - printf("basic test 0\n"); - int list0[4] = {0, 1, 2, 3}; - test0(s, c, 4, list0); - - printf("basic test 1\n"); - int list1[4] = {2, 1, 0, 3}; - test0(s, c, 4, list1); - - int b = c.dequeue(); - c.lock(b); - c.queue(b); - s.retireAndLock(); - - printf("basic test 2\n"); - int list2[4] = {1, 2, 3, 0}; - test0(s, c, 4, list2); - - - printf("resize test\n"); - class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback { - SharedBufferServer& s; - virtual status_t operator()(int bufferCount) const { - return s.resize(bufferCount); - } - public: - SetBufferCountIPC(SharedBufferServer& s) : s(s) { } - } resize(s); - - c.setBufferCount(6, resize); - int list3[6] = {3, 2, 1, 4, 5, 0}; - test0(s, c, 6, list3); - - c.setBufferCount(4, resize); - int list4[4] = {1, 2, 3, 0}; - test0(s, c, 4, list4); - - return 0; -} - -void log(const char* prefix, int *b, size_t num) -{ - printf("%s: ", prefix); - for (size_t i=0 ; i<num ; i++) { - printf("%d ", b[i]); - } - printf("\n"); -} - -// ---------------------------------------------------------------------------- - -void test0( - SharedBufferServer& s, - SharedBufferClient& c, - size_t num, - int* list) -{ - status_t err; - int b[num], u[num], r[num]; - - for (size_t i=0 ; i<num ; i++) { - b[i] = c.dequeue(); - assert(b[i]==list[i]); - } - log("DQ", b, num); - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.lock(b[i]); - assert(err==0); - } - log("LK", b, num-1); - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.queue(b[i]); - assert(err==0); - } - log(" Q", b, num-1); - - - for (size_t i=0 ; i<num-1 ; i++) { - r[i] = s.retireAndLock(); - assert(r[i]==list[i]); - err = s.unlock(r[i]); - assert(err == 0); - } - log("RT", r, num-1); - - err = c.lock(b[num-1]); - assert(err == 0); - log("LK", b+num-1, 1); - - err = c.queue(b[num-1]); - assert(err == 0); - log(" Q", b+num-1, 1); - - r[num-1] = s.retireAndLock(); - assert(r[num-1]==list[num-1]); - err = s.unlock(r[num-1]); - assert(err == 0); - log("RT", r+num-1, 1); - - // ------------------------------------ - printf("\n"); - - for (size_t i=0 ; i<num ; i++) { - b[i] = c.dequeue(); - assert(b[i]==list[i]); - } - log("DQ", b, num); - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.lock(b[i]); - assert(err==0); - } - log("LK", b, num-1); - - for (size_t i=0 ; i<num-1 ; i++) { - u[i] = b[num-2-i]; - } - u[num-1] = b[num-1]; - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.queue(u[i]); - assert(err==0); - } - log(" Q", u, num-1); - - for (size_t i=0 ; i<num-1 ; i++) { - r[i] = s.retireAndLock(); - assert(r[i]==u[i]); - err = s.unlock(r[i]); - assert(err == 0); - } - log("RT", r, num-1); - - err = c.lock(b[num-1]); - assert(err == 0); - log("LK", b+num-1, 1); - - err = c.queue(b[num-1]); - assert(err == 0); - log(" Q", b+num-1, 1); - - r[num-1] = s.retireAndLock(); - assert(r[num-1]==list[num-1]); - err = s.unlock(r[num-1]); - assert(err == 0); - log("RT", r+num-1, 1); - - // ------------------------------------ - printf("\n"); - - for (size_t i=0 ; i<num ; i++) { - b[i] = c.dequeue(); - assert(b[i]==u[i]); - } - log("DQ", b, num); - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.lock(b[i]); - assert(err==0); - } - log("LK", b, num-1); - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.queue(b[i]); - assert(err==0); - } - log(" Q", b, num-1); - - for (size_t i=0 ; i<num-1 ; i++) { - r[i] = s.retireAndLock(); - assert(r[i]==u[i]); - err = s.unlock(r[i]); - assert(err == 0); - } - log("RT", r, num-1); - - err = c.lock(u[num-1]); - assert(err == 0); - log("LK", u+num-1, 1); - - err = c.queue(u[num-1]); - assert(err == 0); - log(" Q", u+num-1, 1); - - r[num-1] = s.retireAndLock(); - assert(r[num-1]==u[num-1]); - err = s.unlock(r[num-1]); - assert(err == 0); - log("RT", r+num-1, 1); - - // ------------------------------------ - printf("\n"); - - b[0] = c.dequeue(); - assert(b[0]==u[0]); - log("DQ", b, 1); - - c.undoDequeue(b[0]); - assert(err == 0); - log("UDQ", b, 1); - - // ------------------------------------ - printf("\n"); - - for (size_t i=0 ; i<num ; i++) { - b[i] = c.dequeue(); - assert(b[i]==u[i]); - } - log("DQ", b, num); - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.lock(b[i]); - assert(err==0); - } - log("LK", b, num-1); - - for (size_t i=0 ; i<num-1 ; i++) { - err = c.queue(b[i]); - assert(err==0); - } - log(" Q", b, num-1); - - for (size_t i=0 ; i<num-1 ; i++) { - r[i] = s.retireAndLock(); - assert(r[i]==u[i]); - err = s.unlock(r[i]); - assert(err == 0); - } - log("RT", r, num-1); - - err = c.lock(u[num-1]); - assert(err == 0); - log("LK", u+num-1, 1); - - err = c.queue(u[num-1]); - assert(err == 0); - log(" Q", u+num-1, 1); - - r[num-1] = s.retireAndLock(); - assert(r[num-1]==u[num-1]); - err = s.unlock(r[num-1]); - assert(err == 0); - log("RT", r+num-1, 1); - printf("\n"); -} diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp index e2e698ef7b3b..440ec00e378d 100644 --- a/libs/ui/Input.cpp +++ b/libs/ui/Input.cpp @@ -7,8 +7,12 @@ //#define LOG_NDEBUG 0 +// Log debug messages about keymap probing. #define DEBUG_PROBE 0 +// Log debug messages about velocity tracking. +#define DEBUG_VELOCITY 0 + #include <stdlib.h> #include <unistd.h> #include <ctype.h> @@ -329,6 +333,27 @@ void PointerCoords::tooManyAxes(int axis) { "cannot contain more than %d axis values.", axis, int(MAX_AXES)); } +bool PointerCoords::operator==(const PointerCoords& other) const { + if (bits != other.bits) { + return false; + } + uint32_t count = __builtin_popcountll(bits); + for (uint32_t i = 0; i < count; i++) { + if (values[i] != other.values[i]) { + return false; + } + } + return true; +} + +void PointerCoords::copyFrom(const PointerCoords& other) { + bits = other.bits; + uint32_t count = __builtin_popcountll(bits); + for (uint32_t i = 0; i < count; i++) { + values[i] = other.values[i]; + } +} + // --- MotionEvent --- @@ -444,6 +469,16 @@ float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, return value; } +ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { + size_t pointerCount = mPointerIds.size(); + for (size_t i = 0; i < pointerCount; i++) { + if (mPointerIds.itemAt(i) == pointerId) { + return i; + } + } + return -1; +} + void MotionEvent::offsetLocation(float xOffset, float yOffset) { mXOffset += xOffset; mYOffset += yOffset; @@ -634,6 +669,208 @@ bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { } +// --- VelocityTracker --- + +VelocityTracker::VelocityTracker() { + clear(); +} + +void VelocityTracker::clear() { + mIndex = 0; + mMovements[0].idBits.clear(); + mActivePointerId = -1; +} + +void VelocityTracker::clearPointers(BitSet32 idBits) { + BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value); + mMovements[mIndex].idBits = remainingIdBits; + + if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) { + mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1; + } +} + +void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) { + if (++mIndex == HISTORY_SIZE) { + mIndex = 0; + } + + while (idBits.count() > MAX_POINTERS) { + idBits.clearBit(idBits.lastMarkedBit()); + } + + Movement& movement = mMovements[mIndex]; + movement.eventTime = eventTime; + movement.idBits = idBits; + uint32_t count = idBits.count(); + for (uint32_t i = 0; i < count; i++) { + movement.positions[i] = positions[i]; + } + + if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) { + mActivePointerId = count != 0 ? idBits.firstMarkedBit() : -1; + } + +#if DEBUG_VELOCITY + LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d", + eventTime, idBits.value, mActivePointerId); + for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) { + uint32_t id = iterBits.firstMarkedBit(); + uint32_t index = idBits.getIndexOfBit(id); + iterBits.clearBit(id); + float vx, vy; + bool available = getVelocity(id, &vx, &vy); + if (available) { + LOGD(" %d: position (%0.3f, %0.3f), vx=%0.3f, vy=%0.3f, speed=%0.3f", + id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy)); + } else { + assert(vx == 0 && vy == 0); + LOGD(" %d: position (%0.3f, %0.3f), velocity not available", + id, positions[index].x, positions[index].y); + } + } +#endif +} + +void VelocityTracker::addMovement(const MotionEvent* event) { + int32_t actionMasked = event->getActionMasked(); + + switch (actionMasked) { + case AMOTION_EVENT_ACTION_DOWN: + // Clear all pointers on down before adding the new movement. + clear(); + break; + case AMOTION_EVENT_ACTION_POINTER_DOWN: { + // Start a new movement trace for a pointer that just went down. + // We do this on down instead of on up because the client may want to query the + // final velocity for a pointer that just went up. + BitSet32 downIdBits; + downIdBits.markBit(event->getActionIndex()); + clearPointers(downIdBits); + break; + } + case AMOTION_EVENT_ACTION_OUTSIDE: + case AMOTION_EVENT_ACTION_CANCEL: + case AMOTION_EVENT_ACTION_SCROLL: + case AMOTION_EVENT_ACTION_UP: + case AMOTION_EVENT_ACTION_POINTER_UP: + // Ignore these actions because they do not convey any new information about + // pointer movement. We also want to preserve the last known velocity of the pointers. + // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position + // of the pointers that went up. ACTION_POINTER_UP does include the new position of + // pointers that remained down but we will also receive an ACTION_MOVE with this + // information if any of them actually moved. Since we don't know how many pointers + // will be going up at once it makes sense to just wait for the following ACTION_MOVE + // before adding the movement. + return; + } + + size_t pointerCount = event->getPointerCount(); + if (pointerCount > MAX_POINTERS) { + pointerCount = MAX_POINTERS; + } + + BitSet32 idBits; + for (size_t i = 0; i < pointerCount; i++) { + idBits.markBit(event->getPointerId(i)); + } + + nsecs_t eventTime; + Position positions[pointerCount]; + + size_t historySize = event->getHistorySize(); + for (size_t h = 0; h < historySize; h++) { + eventTime = event->getHistoricalEventTime(h); + for (size_t i = 0; i < pointerCount; i++) { + positions[i].x = event->getHistoricalX(i, h); + positions[i].y = event->getHistoricalY(i, h); + } + addMovement(eventTime, idBits, positions); + } + + eventTime = event->getEventTime(); + for (size_t i = 0; i < pointerCount; i++) { + positions[i].x = event->getX(i); + positions[i].y = event->getY(i); + } + addMovement(eventTime, idBits, positions); +} + +bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const { + const Movement& newestMovement = mMovements[mIndex]; + if (newestMovement.idBits.hasBit(id)) { + // Find the oldest sample that contains the pointer and that is not older than MAX_AGE. + nsecs_t minTime = newestMovement.eventTime - MAX_AGE; + uint32_t oldestIndex = mIndex; + uint32_t numTouches = 1; + do { + uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1; + const Movement& nextOldestMovement = mMovements[nextOldestIndex]; + if (!nextOldestMovement.idBits.hasBit(id) + || nextOldestMovement.eventTime < minTime) { + break; + } + oldestIndex = nextOldestIndex; + } while (++numTouches < HISTORY_SIZE); + + // Calculate an exponentially weighted moving average of the velocity estimate + // at different points in time measured relative to the oldest sample. + // This is essentially an IIR filter. Newer samples are weighted more heavily + // than older samples. Samples at equal time points are weighted more or less + // equally. + // + // One tricky problem is that the sample data may be poorly conditioned. + // Sometimes samples arrive very close together in time which can cause us to + // overestimate the velocity at that time point. Most samples might be measured + // 16ms apart but some consecutive samples could be only 0.5sm apart because + // the hardware or driver reports them irregularly or in bursts. + float accumVx = 0; + float accumVy = 0; + uint32_t index = oldestIndex; + uint32_t samplesUsed = 0; + const Movement& oldestMovement = mMovements[oldestIndex]; + const Position& oldestPosition = + oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)]; + nsecs_t lastDuration = 0; + while (numTouches-- > 1) { + if (++index == HISTORY_SIZE) { + index = 0; + } + const Movement& movement = mMovements[index]; + nsecs_t duration = movement.eventTime - oldestMovement.eventTime; + + // If the duration between samples is small, we may significantly overestimate + // the velocity. Consequently, we impose a minimum duration constraint on the + // samples that we include in the calculation. + if (duration >= MIN_DURATION) { + const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)]; + float scale = 1000000000.0f / duration; // one over time delta in seconds + float vx = (position.x - oldestPosition.x) * scale; + float vy = (position.y - oldestPosition.y) * scale; + + accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration); + accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration); + + lastDuration = duration; + samplesUsed += 1; + } + } + + // Make sure we used at least one sample. + if (samplesUsed != 0) { + *outVx = accumVx; + *outVy = accumVy; + return true; + } + } + + // No data available for this pointer. + *outVx = 0; + *outVy = 0; + return false; +} + + // --- InputDeviceInfo --- InputDeviceInfo::InputDeviceInfo() { diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp index 5c57a76f40f4..9d1b8b94ecc2 100644 --- a/libs/ui/InputTransport.cpp +++ b/libs/ui/InputTransport.cpp @@ -406,7 +406,7 @@ status_t InputPublisher::publishMotionEvent( for (size_t i = 0; i < pointerCount; i++) { mSharedMessage->motion.pointerIds[i] = pointerIds[i]; - mSharedMessage->motion.sampleData[0].coords[i] = pointerCoords[i]; + mSharedMessage->motion.sampleData[0].coords[i].copyFrom(pointerCoords[i]); } // Cache essential information about the motion event to ensure that a malicious consumer @@ -475,7 +475,7 @@ status_t InputPublisher::appendMotionSample( mMotionEventSampleDataTail->eventTime = eventTime; for (size_t i = 0; i < mMotionEventPointerCount; i++) { - mMotionEventSampleDataTail->coords[i] = pointerCoords[i]; + mMotionEventSampleDataTail->coords[i].copyFrom(pointerCoords[i]); } mMotionEventSampleDataTail = newTail; diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp index e09e755861dc..6e57d93d8b47 100644 --- a/libs/utils/AssetManager.cpp +++ b/libs/utils/AssetManager.cpp @@ -36,6 +36,7 @@ #include <dirent.h> #include <errno.h> #include <assert.h> +#include <strings.h> using namespace android; @@ -1764,4 +1765,3 @@ int AssetManager::ZipSet::getIndex(const String8& zip) const return mZipPath.size()-1; } - diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp index 18f858b4b689..d5dd126065e7 100644 --- a/libs/utils/Looper.cpp +++ b/libs/utils/Looper.cpp @@ -218,14 +218,10 @@ int Looper::pollInner(int timeoutMillis) { // Adjust the timeout based on when the next message is due. if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - if (mNextMessageUptime <= now) { - timeoutMillis = 0; - } else { - uint64_t delay = (mNextMessageUptime - now + 999999LL) / 1000000LL; - if (delay < INT_MAX - && (timeoutMillis < 0 || int(delay) < timeoutMillis)) { - timeoutMillis = int(delay); - } + int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime); + if (messageTimeoutMillis >= 0 + && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) { + timeoutMillis = messageTimeoutMillis; } #if DEBUG_POLL_AND_WAKE LOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d", @@ -444,12 +440,11 @@ int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outDat return result; } - nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC); - if (timeoutNanos <= 0) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + timeoutMillis = toMillisecondTimeoutDelay(now, endTime); + if (timeoutMillis == 0) { return ALOOPER_POLL_TIMEOUT; } - - timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL)); } } } diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp index 784f035dc03a..64a29f58776a 100644 --- a/libs/utils/Timers.cpp +++ b/libs/utils/Timers.cpp @@ -26,6 +26,7 @@ #include <sys/time.h> #include <time.h> #include <errno.h> +#include <limits.h> #ifdef HAVE_WIN32_THREADS #include <windows.h> @@ -53,6 +54,23 @@ nsecs_t systemTime(int clock) #endif } +int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime) +{ + int timeoutDelayMillis; + if (timeoutTime > referenceTime) { + uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime); + if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) { + timeoutDelayMillis = -1; + } else { + timeoutDelayMillis = (timeoutDelay + 999999LL) / 1000000LL; + } + } else { + timeoutDelayMillis = 0; + } + return timeoutDelayMillis; +} + + /* * =========================================================================== * DurationTimer |