diff options
Diffstat (limited to 'libs')
83 files changed, 3284 insertions, 1753 deletions
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp index 3c00db556022..7ac3cc1df718 100644 --- a/libs/camera/Camera.cpp +++ b/libs/camera/Camera.cpp @@ -360,7 +360,8 @@ void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) } // callback from camera service when frame or image is ready -void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) +void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, + camera_frame_metadata_t *metadata) { sp<CameraListener> listener; { @@ -368,7 +369,7 @@ void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) listener = mListener; } if (listener != NULL) { - listener->postData(msgType, dataPtr); + listener->postData(msgType, dataPtr, metadata); } } diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp index d8fef09f04c0..51b96c1fe9dd 100644 --- a/libs/camera/CameraParameters.cpp +++ b/libs/camera/CameraParameters.cpp @@ -86,6 +86,7 @@ const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values"; const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video"; const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw"; const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw"; +const char CameraParameters::KEY_RECORDING_HINT[] = "recording-hint"; const char CameraParameters::TRUE[] = "true"; const char CameraParameters::FALSE[] = "false"; @@ -150,6 +151,7 @@ const char CameraParameters::PIXEL_FORMAT_YUV420P[] = "yuv420p"; const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565"; const char CameraParameters::PIXEL_FORMAT_RGBA8888[] = "rgba8888"; const char CameraParameters::PIXEL_FORMAT_JPEG[] = "jpeg"; +const char CameraParameters::PIXEL_FORMAT_BAYER_RGGB[] = "bayer-rggb"; // Values for focus mode settings. const char CameraParameters::FOCUS_MODE_AUTO[] = "auto"; diff --git a/libs/camera/ICameraClient.cpp b/libs/camera/ICameraClient.cpp index cb3bd0c6180f..183429ad8c7b 100644 --- a/libs/camera/ICameraClient.cpp +++ b/libs/camera/ICameraClient.cpp @@ -51,13 +51,18 @@ public: } // generic data callback from camera service to app with image data - void dataCallback(int32_t msgType, const sp<IMemory>& imageData) + void dataCallback(int32_t msgType, const sp<IMemory>& imageData, + camera_frame_metadata_t *metadata) { LOGV("dataCallback"); Parcel data, reply; data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeInt32(msgType); data.writeStrongBinder(imageData->asBinder()); + if (metadata) { + data.writeInt32(metadata->number_of_faces); + data.write(metadata->faces, sizeof(camera_face_t) * metadata->number_of_faces); + } remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } @@ -96,7 +101,15 @@ status_t BnCameraClient::onTransact( CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder()); - dataCallback(msgType, imageData); + camera_frame_metadata_t *metadata = NULL; + if (data.dataAvail() > 0) { + metadata = new camera_frame_metadata_t; + metadata->number_of_faces = data.readInt32(); + metadata->faces = (camera_face_t *) data.readInplace( + sizeof(camera_face_t) * metadata->number_of_faces); + } + dataCallback(msgType, imageData, metadata); + if (metadata) delete metadata; return NO_ERROR; } break; case DATA_CALLBACK_TIMESTAMP: { diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index 55246dc902e5..babd2c07bc63 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -162,11 +162,15 @@ public: return result; } - virtual status_t connect(int api) { + virtual status_t connect(int api, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(api); remote()->transact(CONNECT, data, &reply); + *outWidth = reply.readInt32(); + *outHeight = reply.readInt32(); + *outTransform = reply.readInt32(); status_t result = reply.readInt32(); return result; } @@ -283,7 +287,12 @@ status_t BnSurfaceTexture::onTransact( case CONNECT: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int api = data.readInt32(); - status_t res = connect(api); + uint32_t outWidth, outHeight, outTransform; + status_t res = connect(api, + &outWidth, &outHeight, &outTransform); + reply->writeInt32(outWidth); + reply->writeInt32(outHeight); + reply->writeInt32(outTransform); reply->writeInt32(res); return NO_ERROR; } break; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index ccf98e500c9a..2c702511de51 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -277,6 +277,11 @@ sp<Surface> Surface::readFromParcel(const Parcel& data) { if (surface == 0) { surface = new Surface(data, binder); sCachedSurfaces.add(binder, surface); + } else { + // The Surface was found in the cache, but we still should clear any + // remaining data from the parcel. + data.readStrongBinder(); // ISurfaceTexture + data.readInt32(); // identity } if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) { surface = 0; diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 16755ad98b2e..7ac43431f1d1 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -104,7 +104,7 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : SurfaceTexture::~SurfaceTexture() { LOGV("SurfaceTexture::~SurfaceTexture"); - freeAllBuffers(); + freeAllBuffersLocked(); } status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) { @@ -154,7 +154,6 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { LOGE("setBufferCount: SurfaceTexture has been abandoned!"); return NO_INIT; } - if (bufferCount > NUM_BUFFER_SLOTS) { LOGE("setBufferCount: bufferCount larger than slots available"); return BAD_VALUE; @@ -168,24 +167,24 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { } } + const int minBufferSlots = mSynchronousMode ? + MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; if (bufferCount == 0) { - const int minBufferSlots = mSynchronousMode ? - MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; mClientBufferCount = 0; bufferCount = (mServerBufferCount >= minBufferSlots) ? mServerBufferCount : minBufferSlots; return setBufferCountServerLocked(bufferCount); } - // We don't allow the client to set a buffer-count less than - // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it. - if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) { + if (bufferCount < minBufferSlots) { + LOGE("setBufferCount: requested buffer count (%d) is less than " + "minimum (%d)", bufferCount, minBufferSlots); return BAD_VALUE; } // here we're guaranteed that the client doesn't have dequeued buffers // and will release all of its buffer references. - freeAllBuffers(); + freeAllBuffersLocked(); mBufferCount = bufferCount; mClientBufferCount = bufferCount; mCurrentTexture = INVALID_BUFFER_SLOT; @@ -228,11 +227,6 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { LOGV("SurfaceTexture::dequeueBuffer"); - if (mAbandoned) { - LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); - return NO_INIT; - } - if ((w && !h) || (!w && h)) { LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); return BAD_VALUE; @@ -246,10 +240,15 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, int dequeuedCount = 0; bool tryAgain = true; while (tryAgain) { + if (mAbandoned) { + LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + // We need to wait for the FIFO to drain if the number of buffer // needs to change. // - // The condition "number of buffer needs to change" is true if + // The condition "number of buffers needs to change" is true if // - the client doesn't care about how many buffers there are // - AND the actual number of buffer is different from what was // set in the last setBufferCountServer() @@ -261,31 +260,24 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, // As long as this condition is true AND the FIFO is not empty, we // wait on mDequeueCondition. - int minBufferCountNeeded = mSynchronousMode ? + const int minBufferCountNeeded = mSynchronousMode ? MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; - if (!mClientBufferCount && + const bool numberOfBuffersNeedsToChange = !mClientBufferCount && ((mServerBufferCount != mBufferCount) || - (mServerBufferCount < minBufferCountNeeded))) { + (mServerBufferCount < minBufferCountNeeded)); + + if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) { // wait for the FIFO to drain - while (!mQueue.isEmpty()) { - mDequeueCondition.wait(mMutex); - if (mAbandoned) { - LOGE("dequeueBuffer: SurfaceTexture was abandoned while " - "blocked!"); - return NO_INIT; - } - } - minBufferCountNeeded = mSynchronousMode ? - MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; + mDequeueCondition.wait(mMutex); + // NOTE: we continue here because we need to reevaluate our + // whole state (eg: we could be abandoned or disconnected) + continue; } - - if (!mClientBufferCount && - ((mServerBufferCount != mBufferCount) || - (mServerBufferCount < minBufferCountNeeded))) { + if (numberOfBuffersNeedsToChange) { // here we're guaranteed that mQueue is empty - freeAllBuffers(); + freeAllBuffersLocked(); mBufferCount = mServerBufferCount; if (mBufferCount < minBufferCountNeeded) mBufferCount = minBufferCountNeeded; @@ -414,9 +406,9 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { if (!enabled) { // going to asynchronous mode, drain the queue - while (mSynchronousMode != enabled && !mQueue.isEmpty()) { - mDequeueCondition.wait(mMutex); - } + err = drainQueueLocked(); + if (err != NO_ERROR) + return err; } if (mSynchronousMode != enabled) { @@ -548,7 +540,8 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { return OK; } -status_t SurfaceTexture::connect(int api) { +status_t SurfaceTexture::connect(int api, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); @@ -569,6 +562,9 @@ status_t SurfaceTexture::connect(int api) { err = -EINVAL; } else { mConnectedApi = api; + *outWidth = mDefaultWidth; + *outHeight = mDefaultHeight; + *outTransform = 0; } break; default: @@ -594,7 +590,9 @@ status_t SurfaceTexture::disconnect(int api) { case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi == api) { + drainQueueAndFreeBuffersLocked(); mConnectedApi = NO_CONNECTED_API; + mDequeueCondition.signal(); } else { LOGE("disconnect: connected to another api (cur=%d, req=%d)", mConnectedApi, api); @@ -628,6 +626,11 @@ status_t SurfaceTexture::updateTexImage() { LOGV("SurfaceTexture::updateTexImage"); Mutex::Autolock lock(mMutex); + if (mAbandoned) { + LOGE("calling updateTexImage() on an abandoned SurfaceTexture"); + return NO_INIT; + } + // In asynchronous mode the list is guaranteed to be one buffer // deep, while in synchronous mode we use the oldest buffer. if (!mQueue.empty()) { @@ -638,6 +641,10 @@ status_t SurfaceTexture::updateTexImage() { EGLImageKHR image = mSlots[buf].mEglImage; if (image == EGL_NO_IMAGE_KHR) { EGLDisplay dpy = eglGetCurrentDisplay(); + if (mSlots[buf].mGraphicBuffer == 0) { + LOGE("buffer at slot %d is null", buf); + return BAD_VALUE; + } image = createImage(dpy, mSlots[buf].mGraphicBuffer); mSlots[buf].mEglImage = image; mSlots[buf].mEglDisplay = dpy; @@ -827,16 +834,64 @@ void SurfaceTexture::setFrameAvailableListener( mFrameAvailableListener = listener; } -void SurfaceTexture::freeAllBuffers() { +void SurfaceTexture::freeBufferLocked(int i) { + mSlots[i].mGraphicBuffer = 0; + mSlots[i].mBufferState = BufferSlot::FREE; + if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage); + mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; + mSlots[i].mEglDisplay = EGL_NO_DISPLAY; + } +} + +void SurfaceTexture::freeAllBuffersLocked() { + LOGW_IF(!mQueue.isEmpty(), + "freeAllBuffersLocked called but mQueue is not empty"); for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i].mGraphicBuffer = 0; - mSlots[i].mBufferState = BufferSlot::FREE; - if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage); - mSlots[i].mEglImage = EGL_NO_IMAGE_KHR; - mSlots[i].mEglDisplay = EGL_NO_DISPLAY; + freeBufferLocked(i); + } +} + +void SurfaceTexture::freeAllBuffersExceptHeadLocked() { + LOGW_IF(!mQueue.isEmpty(), + "freeAllBuffersExceptCurrentLocked called but mQueue is not empty"); + int head = -1; + if (!mQueue.empty()) { + Fifo::iterator front(mQueue.begin()); + head = *front; + } + for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { + if (i != head) { + freeBufferLocked(i); + } + } +} + +status_t SurfaceTexture::drainQueueLocked() { + while (mSynchronousMode && !mQueue.isEmpty()) { + mDequeueCondition.wait(mMutex); + if (mAbandoned) { + LOGE("drainQueueLocked: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + if (mConnectedApi == NO_CONNECTED_API) { + LOGE("drainQueueLocked: SurfaceTexture is not connected!"); + return NO_INIT; } } + return NO_ERROR; +} + +status_t SurfaceTexture::drainQueueAndFreeBuffersLocked() { + status_t err = drainQueueLocked(); + if (err == NO_ERROR) { + if (mSynchronousMode) { + freeAllBuffersLocked(); + } else { + freeAllBuffersExceptHeadLocked(); + } + } + return err; } EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy, @@ -908,8 +963,10 @@ int SurfaceTexture::query(int what, int* outValue) void SurfaceTexture::abandon() { Mutex::Autolock lock(mMutex); - freeAllBuffers(); + mQueue.clear(); mAbandoned = true; + mCurrentTextureBuf.clear(); + freeAllBuffersLocked(); mDequeueCondition.signal(); } @@ -965,13 +1022,24 @@ void SurfaceTexture::dump(String8& result, const char* prefix, for (int i=0 ; i<mBufferCount ; i++) { const BufferSlot& slot(mSlots[i]); snprintf(buffer, SIZE, - "%s%s[%02d] state=%-8s, crop=[%d,%d,%d,%d], transform=0x%02x, " - "timestamp=%lld\n", - prefix, (i==mCurrentTexture)?">":" ", i, stateName(slot.mBufferState), + "%s%s[%02d] " + "state=%-8s, crop=[%d,%d,%d,%d], " + "transform=0x%02x, timestamp=%lld", + prefix, (i==mCurrentTexture)?">":" ", i, + stateName(slot.mBufferState), slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, slot.mCrop.bottom, slot.mTransform, slot.mTimestamp ); result.append(buffer); + + const sp<GraphicBuffer>& buf(slot.mGraphicBuffer); + if (buf != NULL) { + snprintf(buffer, SIZE, + ", %p [%4ux%4u:%4u,%3X]", + buf->handle, buf->width, buf->height, buf->stride, buf->format); + result.append(buffer); + } + result.append("\n"); } } diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index e6837ea3607e..e91be84c48a6 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -258,10 +258,10 @@ int SurfaceTextureClient::perform(int operation, va_list args) int res = NO_ERROR; switch (operation) { case NATIVE_WINDOW_CONNECT: - res = dispatchConnect(args); + // deprecated. must return NO_ERROR. break; case NATIVE_WINDOW_DISCONNECT: - res = dispatchDisconnect(args); + // deprecated. must return NO_ERROR. break; case NATIVE_WINDOW_SET_USAGE: res = dispatchSetUsage(args); @@ -296,6 +296,12 @@ int SurfaceTextureClient::perform(int operation, va_list args) case NATIVE_WINDOW_SET_SCALING_MODE: res = dispatchSetScalingMode(args); break; + case NATIVE_WINDOW_API_CONNECT: + res = dispatchConnect(args); + break; + case NATIVE_WINDOW_API_DISCONNECT: + res = dispatchDisconnect(args); + break; default: res = NAME_NOT_FOUND; break; @@ -379,7 +385,8 @@ int SurfaceTextureClient::dispatchUnlockAndPost(va_list args) { int SurfaceTextureClient::connect(int api) { LOGV("SurfaceTextureClient::connect"); Mutex::Autolock lock(mMutex); - int err = mSurfaceTexture->connect(api); + int err = mSurfaceTexture->connect(api, + &mDefaultWidth, &mDefaultHeight, &mTransformHint); if (!err && api == NATIVE_WINDOW_API_CPU) { mConnectedToCpu = true; } diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index c5858e93f23b..24ec4e8378ae 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -142,7 +142,6 @@ void Caches::dumpMemoryUsage(String8 &log) { void Caches::clearGarbage() { textureCache.clearGarbage(); - gradientCache.clearGarbage(); pathCache.clearGarbage(); Mutex::Autolock _l(mGarbageLock); diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h index 5db73db9fc35..7cbb39da9ee0 100644 --- a/libs/hwui/Debug.h +++ b/libs/hwui/Debug.h @@ -20,6 +20,9 @@ // Turn on to check for OpenGL errors on each frame #define DEBUG_OPENGL 1 +// Turn on to display informations about the GPU +#define DEBUG_EXTENSIONS 0 + // Turn on to enable initialization information #define DEBUG_INIT 0 diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h index eceb5c1cb0df..38d113000480 100644 --- a/libs/hwui/Extensions.h +++ b/libs/hwui/Extensions.h @@ -23,6 +23,8 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#include "Debug.h" + namespace android { namespace uirenderer { @@ -31,15 +33,20 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// // Debug -#define DEBUG_EXTENSIONS 0 - -// Debug #if DEBUG_EXTENSIONS #define EXT_LOGD(...) LOGD(__VA_ARGS__) #else #define EXT_LOGD(...) #endif +// Vendor strings + +#define VENDOR_IMG "Imagination Technologies" + +/////////////////////////////////////////////////////////////////////////////// +// Classes +/////////////////////////////////////////////////////////////////////////////// + class Extensions { public: Extensions() { @@ -58,17 +65,21 @@ public: } while (head); mHasNPot = hasExtension("GL_OES_texture_npot"); - mHasDrawPath = hasExtension("GL_NV_draw_path"); - mHasCoverageSample = hasExtension("GL_NV_coverage_sample"); mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch"); + const char* vendor = (const char*) glGetString(GL_VENDOR); + EXT_LOGD("Vendor: %s", vendor); + mNeedsHighpTexCoords = strcmp(vendor, VENDOR_IMG) == 0; + + // We don't need to copy the string, the OpenGL ES spec + // guarantees the result of glGetString to point to a + // static string as long as our OpenGL context is valid mExtensions = buffer; } inline bool hasNPot() const { return mHasNPot; } - inline bool hasDrawPath() const { return mHasDrawPath; } - inline bool hasCoverageSample() const { return mHasCoverageSample; } inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; } + inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; } bool hasExtension(const char* extension) const { const String8 s(extension); @@ -85,8 +96,7 @@ private: const char* mExtensions; bool mHasNPot; - bool mHasDrawPath; - bool mHasCoverageSample; + bool mNeedsHighpTexCoords; bool mHasFramebufferFetch; }; // class Extensions diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 9bf3de81ba93..9acf99be1a15 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -44,9 +44,11 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// Font::Font(FontRenderer* state, uint32_t fontId, float fontSize, - int flags, uint32_t italicStyle, uint32_t scaleX) : + int flags, uint32_t italicStyle, uint32_t scaleX, + SkPaint::Style style, uint32_t strokeWidth) : mState(state), mFontId(fontId), mFontSize(fontSize), - mFlags(flags), mItalicStyle(italicStyle), mScaleX(scaleX) { + mFlags(flags), mItalicStyle(italicStyle), mScaleX(scaleX), + mStyle(style), mStrokeWidth(mStrokeWidth) { } @@ -283,19 +285,22 @@ Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) { } Font* Font::create(FontRenderer* state, uint32_t fontId, float fontSize, - int flags, uint32_t italicStyle, uint32_t scaleX) { + int flags, uint32_t italicStyle, uint32_t scaleX, + SkPaint::Style style, uint32_t strokeWidth) { Vector<Font*> &activeFonts = state->mActiveFonts; for (uint32_t i = 0; i < activeFonts.size(); i++) { Font* font = activeFonts[i]; if (font->mFontId == fontId && font->mFontSize == fontSize && font->mFlags == flags && font->mItalicStyle == italicStyle && - font->mScaleX == scaleX) { + font->mScaleX == scaleX && font->mStyle == style && + (style == SkPaint::kFill_Style || font->mStrokeWidth == strokeWidth)) { return font; } } - Font* newFont = new Font(state, fontId, fontSize, flags, italicStyle, scaleX); + Font* newFont = new Font(state, fontId, fontSize, flags, italicStyle, + scaleX, style, strokeWidth); activeFonts.push(newFont); return newFont; } @@ -690,7 +695,11 @@ void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) { uint32_t italicStyle = *(uint32_t*) &skewX; const float scaleXFloat = paint->getTextScaleX(); uint32_t scaleX = *(uint32_t*) &scaleXFloat; - mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle, scaleX); + SkPaint::Style style = paint->getStyle(); + const float strokeWidthFloat = paint->getStrokeWidth(); + uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat; + mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle, + scaleX, style, strokeWidth); const float maxPrecacheFontSize = 40.0f; bool isNewFont = currentNumFonts != mActiveFonts.size(); diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index 24ed6fa4756f..1922812b387e 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -82,7 +82,8 @@ public: * Creates a new font associated with the specified font state. */ static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, - int flags, uint32_t italicStyle, uint32_t scaleX); + int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, + uint32_t strokeWidth); protected: friend class FontRenderer; @@ -128,7 +129,7 @@ protected: }; Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, - uint32_t scaleX); + uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); // Cache of glyphs DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; @@ -157,6 +158,8 @@ protected: int mFlags; uint32_t mItalicStyle; uint32_t mScaleX; + SkPaint::Style mStyle; + uint32_t mStrokeWidth; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 996acd5bceac..aacf22a19e7e 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -35,7 +35,7 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// GradientCache::GradientCache(): - mCache(GenerationCache<SkShader*, Texture*>::kUnlimitedCapacity), + mCache(GenerationCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity), mSize(0), mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE)) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, NULL) > 0) { @@ -49,7 +49,7 @@ GradientCache::GradientCache(): } GradientCache::GradientCache(uint32_t maxByteSize): - mCache(GenerationCache<SkShader*, Texture*>::kUnlimitedCapacity), + mCache(GenerationCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity), mSize(0), mMaxSize(maxByteSize) { mCache.setOnEntryRemovedListener(this); } @@ -81,9 +81,8 @@ void GradientCache::setMaxSize(uint32_t maxSize) { // Callbacks /////////////////////////////////////////////////////////////////////////////// -void GradientCache::operator()(SkShader*& shader, Texture*& texture) { - // Already locked here - if (shader) { +void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) { + if (texture) { const uint32_t size = texture->width * texture->height * 4; mSize -= size; } @@ -98,34 +97,25 @@ void GradientCache::operator()(SkShader*& shader, Texture*& texture) { // Caching /////////////////////////////////////////////////////////////////////////////// -Texture* GradientCache::get(SkShader* shader) { - return mCache.get(shader); -} +Texture* GradientCache::get(uint32_t* colors, float* positions, + int count, SkShader::TileMode tileMode) { -void GradientCache::remove(SkShader* shader) { - mCache.remove(shader); -} + GradientCacheEntry gradient(colors, positions, count, tileMode); + Texture* texture = mCache.get(gradient); -void GradientCache::removeDeferred(SkShader* shader) { - Mutex::Autolock _l(mLock); - mGarbage.push(shader); -} - -void GradientCache::clearGarbage() { - Mutex::Autolock _l(mLock); - size_t count = mGarbage.size(); - for (size_t i = 0; i < count; i++) { - mCache.remove(mGarbage.itemAt(i)); + if (!texture) { + texture = addLinearGradient(gradient, colors, positions, count, tileMode); } - mGarbage.clear(); + + return texture; } void GradientCache::clear() { mCache.clear(); } -Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors, - float* positions, int count, SkShader::TileMode tileMode) { +Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient, + uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1); bitmap.allocPixels(); @@ -156,7 +146,7 @@ Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors, generateTexture(&bitmap, texture); mSize += size; - mCache.put(shader, texture); + mCache.put(gradient, texture); return texture; } diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index 30da46209800..733985317c7c 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -22,17 +22,85 @@ #include <utils/Vector.h> #include "Texture.h" +#include "utils/Compare.h" #include "utils/GenerationCache.h" namespace android { namespace uirenderer { +struct GradientCacheEntry { + GradientCacheEntry() { + count = 0; + colors = NULL; + positions = NULL; + tileMode = SkShader::kClamp_TileMode; + } + + GradientCacheEntry(uint32_t* colors, float* positions, int count, + SkShader::TileMode tileMode) { + copy(colors, positions, count, tileMode); + } + + GradientCacheEntry(const GradientCacheEntry& entry) { + copy(entry.colors, entry.positions, entry.count, entry.tileMode); + } + + ~GradientCacheEntry() { + delete[] colors; + delete[] positions; + } + + GradientCacheEntry& operator=(const GradientCacheEntry& entry) { + if (this != &entry) { + delete[] colors; + delete[] positions; + + copy(entry.colors, entry.positions, entry.count, entry.tileMode); + } + + return *this; + } + + bool operator<(const GradientCacheEntry& r) const { + const GradientCacheEntry& rhs = (const GradientCacheEntry&) r; + LTE_INT(count) { + LTE_INT(tileMode) { + int result = memcmp(colors, rhs.colors, count * sizeof(uint32_t)); + if (result< 0) return true; + else if (result == 0) { + result = memcmp(positions, rhs.positions, count * sizeof(float)); + if (result < 0) return true; + } + } + } + return false; + } + + uint32_t* colors; + float* positions; + int count; + SkShader::TileMode tileMode; + +private: + + void copy(uint32_t* colors, float* positions, int count, SkShader::TileMode tileMode) { + this->count = count; + this->colors = new uint32_t[count]; + this->positions = new float[count]; + this->tileMode = tileMode; + + memcpy(this->colors, colors, count * sizeof(uint32_t)); + memcpy(this->positions, positions, count * sizeof(float)); + } + +}; // GradientCacheEntry + /** * A simple LRU gradient cache. The cache has a maximum size expressed in bytes. * Any texture added to the cache causing the cache to grow beyond the maximum * allowed size will also cause the oldest texture to be kicked out. */ -class GradientCache: public OnEntryRemoved<SkShader*, Texture*> { +class GradientCache: public OnEntryRemoved<GradientCacheEntry, Texture*> { public: GradientCache(); GradientCache(uint32_t maxByteSize); @@ -42,32 +110,13 @@ public: * Used as a callback when an entry is removed from the cache. * Do not invoke directly. */ - void operator()(SkShader*& shader, Texture*& texture); + void operator()(GradientCacheEntry& shader, Texture*& texture); /** - * Adds a new linear gradient to the cache. The generated texture is - * returned. - */ - Texture* addLinearGradient(SkShader* shader, uint32_t* colors, float* positions, - int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode); - /** * Returns the texture associated with the specified shader. */ - Texture* get(SkShader* shader); - /** - * Removes the texture associated with the specified shader. - * Upon remove the texture is freed. - */ - void remove(SkShader* shader); - /** - * Removes the texture associated with the specified shader. This is meant - * to be called from threads that are not the EGL context thread. - */ - void removeDeferred(SkShader* shader); - /** - * Process deferred removals. - */ - void clearGarbage(); + Texture* get(uint32_t* colors, float* positions, + int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode); /** * Clears the cache. This causes all textures to be deleted. */ @@ -87,9 +136,17 @@ public: uint32_t getSize(); private: + /** + * Adds a new linear gradient to the cache. The generated texture is + * returned. + */ + Texture* addLinearGradient(GradientCacheEntry& gradient, + uint32_t* colors, float* positions, int count, + SkShader::TileMode tileMode = SkShader::kClamp_TileMode); + void generateTexture(SkBitmap* bitmap, Texture* texture); - GenerationCache<SkShader*, Texture*> mCache; + GenerationCache<GradientCacheEntry, Texture*> mCache; uint32_t mSize; uint32_t mMaxSize; diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index dd75497c19a9..a8ae5c6eebd9 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -203,6 +203,10 @@ struct Layer { return texTransform; } + inline mat4& getTransform() { + return transform; + } + /** * Bounds of the layer. */ @@ -282,6 +286,11 @@ private: */ mat4 texTransform; + /** + * Optional transform. + */ + mat4 transform; + }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h index a0eae592b60f..63bb824c1281 100644 --- a/libs/hwui/LayerCache.h +++ b/libs/hwui/LayerCache.h @@ -119,10 +119,6 @@ private: mHeight = uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); } - LayerEntry(const LayerEntry& entry): - mLayer(entry.mLayer), mWidth(entry.mWidth), mHeight(entry.mHeight) { - } - LayerEntry(Layer* layer): mLayer(layer), mWidth(layer->getWidth()), mHeight(layer->getHeight()) { } diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 9fc5131ee931..769c99cf293a 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -51,6 +51,7 @@ void Matrix4::loadIdentity() { data[kTranslateZ] = 0.0f; data[kPerspective2] = 1.0f; + mIsIdentity = true; mSimpleMatrix = true; } @@ -71,14 +72,21 @@ bool Matrix4::isSimple() { return mSimpleMatrix; } +bool Matrix4::isIdentity() { + return mIsIdentity; +} + void Matrix4::load(const float* v) { memcpy(data, v, sizeof(data)); + // TODO: Do something smarter here mSimpleMatrix = false; + mIsIdentity = false; } void Matrix4::load(const Matrix4& v) { memcpy(data, v.data, sizeof(data)); mSimpleMatrix = v.mSimpleMatrix; + mIsIdentity = v.mIsIdentity; } void Matrix4::load(const SkMatrix& v) { @@ -99,6 +107,7 @@ void Matrix4::load(const SkMatrix& v) { data[kScaleZ] = 1.0f; mSimpleMatrix = (v.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)); + mIsIdentity = v.isIdentity(); } void Matrix4::copyTo(SkMatrix& v) const { @@ -148,6 +157,7 @@ void Matrix4::loadInverse(const Matrix4& v) { v.data[kSkewX] * v.data[kSkewY]) * scale; mSimpleMatrix = v.mSimpleMatrix; + mIsIdentity = v.mIsIdentity; } void Matrix4::copyTo(float* v) const { @@ -166,20 +176,27 @@ void Matrix4::multiply(float v) { for (int i = 0; i < 16; i++) { data[i] *= v; } + mIsIdentity = false; } void Matrix4::loadTranslate(float x, float y, float z) { loadIdentity(); + data[kTranslateX] = x; data[kTranslateY] = y; data[kTranslateZ] = z; + + mIsIdentity = false; } void Matrix4::loadScale(float sx, float sy, float sz) { loadIdentity(); + data[kScaleX] = sx; data[kScaleY] = sy; data[kScaleZ] = sz; + + mIsIdentity = false; } void Matrix4::loadSkew(float sx, float sy) { @@ -198,6 +215,7 @@ void Matrix4::loadSkew(float sx, float sy) { data[kPerspective2] = 1.0f; mSimpleMatrix = false; + mIsIdentity = false; } void Matrix4::loadRotate(float angle, float x, float y, float z) { @@ -238,6 +256,7 @@ void Matrix4::loadRotate(float angle, float x, float y, float z) { data[kScaleZ] = z * z * nc + c; mSimpleMatrix = false; + mIsIdentity = false; } void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) { @@ -262,16 +281,20 @@ void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) { } mSimpleMatrix = u.mSimpleMatrix && v.mSimpleMatrix; + mIsIdentity = false; } void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) { loadIdentity(); + data[kScaleX] = 2.0f / (right - left); data[kScaleY] = 2.0f / (top - bottom); data[kScaleZ] = -2.0f / (far - near); data[kTranslateX] = -(right + left) / (right - left); data[kTranslateY] = -(top + bottom) / (top - bottom); data[kTranslateZ] = -(far + near) / (far - near); + + mIsIdentity = false; } #define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c) diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index 2fa6ab7757a7..56fd37de813b 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -112,6 +112,7 @@ public: bool isPureTranslate(); bool isSimple(); + bool isIdentity(); bool changesBounds(); @@ -128,6 +129,7 @@ public: private: bool mSimpleMatrix; + bool mIsIdentity; inline float get(int i, int j) const { return data[i * 4 + j]; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index e67abbd7e17d..a0f806a209ba 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -627,6 +627,12 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { float alpha = layer->getAlpha() / 255.0f; + mat4& transform = layer->getTransform(); + if (!transform.isIdentity()) { + save(0); + mSnapshot->transform->multiply(transform); + } + setupDraw(); if (layer->getRenderTarget() == GL_TEXTURE_2D) { setupDrawWithTexture(); @@ -663,6 +669,10 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); finishDrawTexture(); + + if (!transform.isIdentity()) { + restore(); + } } void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { @@ -924,13 +934,6 @@ void OpenGLRenderer::setMatrix(SkMatrix* matrix) { mSnapshot->transform->load(*matrix); } -const float* OpenGLRenderer::getMatrix() const { - if (mSnapshot->fbo != 0) { - return &mSnapshot->transform->data[0]; - } - return &mIdentity.data[0]; -} - void OpenGLRenderer::getMatrix(SkMatrix* matrix) { mSnapshot->transform->copyTo(*matrix); } @@ -1489,13 +1492,19 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f); const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f); - texture->setFilter(GL_NEAREST, GL_NEAREST, true); + GLenum filter = GL_NEAREST; + if (u1 > 0.0f || u2 < 1.0f || v1 > 0.0f || v2 < 1.0f) { + filter = GL_LINEAR; + } + texture->setFilter(filter, filter, true); + drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop), texture->id, alpha / 255.0f, mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, false, true); } else { texture->setFilter(GL_LINEAR, GL_LINEAR, true); + drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f, mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index fa893f02a69d..14b22b39cfdb 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -87,7 +87,6 @@ public: virtual void scale(float sx, float sy); virtual void skew(float sx, float sy); - const float* getMatrix() const; void getMatrix(SkMatrix* matrix); virtual void setMatrix(SkMatrix* matrix); virtual void concatMatrix(SkMatrix* matrix); diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h index 62d0ce190aec..91b603fcc380 100644 --- a/libs/hwui/PatchCache.h +++ b/libs/hwui/PatchCache.h @@ -80,13 +80,6 @@ private: emptyCount(emptyCount), colorKey(colorKey) { } - PatchDescription(const PatchDescription& description): - bitmapWidth(description.bitmapWidth), bitmapHeight(description.bitmapHeight), - pixelWidth(description.pixelWidth), pixelHeight(description.pixelHeight), - xCount(description.xCount), yCount(description.yCount), - emptyCount(description.emptyCount), colorKey(description.colorKey) { - } - bool operator<(const PatchDescription& rhs) const { LTE_FLOAT(bitmapWidth) { LTE_FLOAT(bitmapHeight) { diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index 7ff8b74810dd..4904a587f6f3 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -41,10 +41,6 @@ struct PathCacheEntry: public ShapeCacheEntry { path = NULL; } - PathCacheEntry(const PathCacheEntry& entry): ShapeCacheEntry(entry) { - path = entry.path; - } - bool lessThan(const ShapeCacheEntry& r) const { const PathCacheEntry& rhs = (const PathCacheEntry&) r; LTE_INT(path) { diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index d419e3eab38c..c2383f4c7256 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -18,6 +18,7 @@ #include <utils/String8.h> +#include "Caches.h" #include "ProgramCache.h" namespace android { @@ -64,10 +65,18 @@ const char* gVS_Header_Varyings_HasTexture = const char* gVS_Header_Varyings_IsAA = "varying float widthProportion;\n" "varying float lengthProportion;\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_HasBitmap[2] = { + // Default precision + "varying vec2 outBitmapTexCoords;\n", + // High precision + "varying highp vec2 outBitmapTexCoords;\n" +}; +const char* gVS_Header_Varyings_PointHasBitmap[2] = { + // Default precision + "varying vec2 outPointBitmapTexCoords;\n", + // High precision + "varying highp vec2 outPointBitmapTexCoords;\n" +}; const char* gVS_Header_Varyings_HasGradient[3] = { // Linear "varying vec2 linear;\n", @@ -417,9 +426,10 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { + int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0; shader.append(description.isPoint ? - gVS_Header_Varyings_PointHasBitmap : - gVS_Header_Varyings_HasBitmap); + gVS_Header_Varyings_PointHasBitmap[index] : + gVS_Header_Varyings_HasBitmap[index]); } // Begin the shader @@ -455,7 +465,6 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description } String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) { - // Set the default precision String8 shader; const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; @@ -479,9 +488,10 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); } if (description.hasBitmap) { + int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0; shader.append(description.isPoint ? - gVS_Header_Varyings_PointHasBitmap : - gVS_Header_Varyings_HasBitmap); + gVS_Header_Varyings_PointHasBitmap[index] : + gVS_Header_Varyings_HasBitmap[index]); } // Uniforms diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index cd2c40506869..ee7398303c0c 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -166,9 +166,6 @@ void ResourceCache::destructor(SkiaShader* resource) { ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; if (ref == NULL) { // If we're not tracking this resource, just delete it - if (Caches::hasInstance()) { - Caches::getInstance().gradientCache.removeDeferred(resource->getSkShader()); - } delete resource; return; } @@ -220,9 +217,6 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r break; case kShader: { SkiaShader* shader = (SkiaShader*) resource; - if (Caches::hasInstance()) { - Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader()); - } delete shader; } break; diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h index 33953be5d20d..0660b690a1cd 100644 --- a/libs/hwui/ShapeCache.h +++ b/libs/hwui/ShapeCache.h @@ -96,12 +96,6 @@ struct ShapeCacheEntry { pathEffect = NULL; } - ShapeCacheEntry(const ShapeCacheEntry& entry): - shapeType(entry.shapeType), join(entry.join), cap(entry.cap), - style(entry.style), miter(entry.miter), - strokeWidth(entry.strokeWidth), pathEffect(entry.pathEffect) { - } - ShapeCacheEntry(ShapeType type, SkPaint* paint) { shapeType = type; join = paint->getStrokeJoin(); @@ -167,14 +161,6 @@ struct RoundRectShapeCacheEntry: public ShapeCacheEntry { mRy = 0; } - RoundRectShapeCacheEntry(const RoundRectShapeCacheEntry& entry): - ShapeCacheEntry(entry) { - mWidth = entry.mWidth; - mHeight = entry.mHeight; - mRx = entry.mRx; - mRy = entry.mRy; - } - bool lessThan(const ShapeCacheEntry& r) const { const RoundRectShapeCacheEntry& rhs = (const RoundRectShapeCacheEntry&) r; LTE_INT(mWidth) { @@ -206,11 +192,6 @@ struct CircleShapeCacheEntry: public ShapeCacheEntry { mRadius = 0; } - CircleShapeCacheEntry(const CircleShapeCacheEntry& entry): - ShapeCacheEntry(entry) { - mRadius = entry.mRadius; - } - bool lessThan(const ShapeCacheEntry& r) const { const CircleShapeCacheEntry& rhs = (const CircleShapeCacheEntry&) r; LTE_INT(mRadius) { @@ -234,12 +215,6 @@ struct OvalShapeCacheEntry: public ShapeCacheEntry { mWidth = mHeight = 0; } - OvalShapeCacheEntry(const OvalShapeCacheEntry& entry): - ShapeCacheEntry(entry) { - mWidth = entry.mWidth; - mHeight = entry.mHeight; - } - bool lessThan(const ShapeCacheEntry& r) const { const OvalShapeCacheEntry& rhs = (const OvalShapeCacheEntry&) r; LTE_INT(mWidth) { @@ -266,12 +241,6 @@ struct RectShapeCacheEntry: public ShapeCacheEntry { mWidth = mHeight = 0; } - RectShapeCacheEntry(const RectShapeCacheEntry& entry): - ShapeCacheEntry(entry) { - mWidth = entry.mWidth; - mHeight = entry.mHeight; - } - bool lessThan(const ShapeCacheEntry& r) const { const RectShapeCacheEntry& rhs = (const RectShapeCacheEntry&) r; LTE_INT(mWidth) { @@ -306,15 +275,6 @@ struct ArcShapeCacheEntry: public ShapeCacheEntry { mUseCenter = 0; } - ArcShapeCacheEntry(const ArcShapeCacheEntry& entry): - ShapeCacheEntry(entry) { - mWidth = entry.mWidth; - mHeight = entry.mHeight; - mStartAngle = entry.mStartAngle; - mSweepAngle = entry.mSweepAngle; - mUseCenter = entry.mUseCenter; - } - bool lessThan(const ShapeCacheEntry& r) const { const ArcShapeCacheEntry& rhs = (const ArcShapeCacheEntry&) r; LTE_INT(mWidth) { diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 1a60dca04248..242829536aaa 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -144,8 +144,11 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, // Uniforms bindTexture(texture, mWrapS, mWrapT); - GLenum filter = textureTransform.isPureTranslate() ? GL_NEAREST : GL_LINEAR; - texture->setFilter(filter, filter); + // Assume linear here; we should really check the transform in + // ::updateTransforms() but we don't have the texture object + // available at that point. The optimization is not worth the + // effort for now. + texture->setFilter(GL_LINEAR, GL_LINEAR); glUniform1i(program->getUniform("bitmapSampler"), textureSlot); glUniformMatrix4fv(program->getUniform("textureTransform"), 1, @@ -222,10 +225,7 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV GLuint textureSlot = (*textureUnit)++; glActiveTexture(gTextureUnitsMap[textureSlot]); - Texture* texture = mGradientCache->get(mKey); - if (!texture) { - texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX); - } + Texture* texture = mGradientCache->get(mColors, mPositions, mCount, mTileX); mat4 screenSpace; computeScreenSpaceMatrix(screenSpace, modelView); @@ -337,10 +337,7 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi GLuint textureSlot = (*textureUnit)++; glActiveTexture(gTextureUnitsMap[textureSlot]); - Texture* texture = mGradientCache->get(mKey); - if (!texture) { - texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount); - } + Texture* texture = mGradientCache->get(mColors, mPositions, mCount); mat4 screenSpace; computeScreenSpaceMatrix(screenSpace, modelView); diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h index 535f713c684c..3ba012353ca7 100644 --- a/libs/rs/RenderScript.h +++ b/libs/rs/RenderScript.h @@ -52,8 +52,8 @@ void rsaElementGetSubElements(RsContext, RsElement, uint32_t *ids, const char ** RsDevice rsDeviceCreate(); void rsDeviceDestroy(RsDevice dev); void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value); -RsContext rsContextCreate(RsDevice dev, uint32_t version); -RsContext rsContextCreateGL(RsDevice dev, uint32_t version, RsSurfaceConfig sc, uint32_t dpi); +RsContext rsContextCreate(RsDevice dev, uint32_t version, uint32_t sdkVersion); +RsContext rsContextCreateGL(RsDevice dev, uint32_t version, uint32_t sdkVersion, RsSurfaceConfig sc, uint32_t dpi); #include "rsgApiFuncDecl.h" diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp index 0c0aa10ad7ad..176dd182b951 100644 --- a/libs/rs/driver/rsdBcc.cpp +++ b/libs/rs/driver/rsdBcc.cpp @@ -19,7 +19,7 @@ #include "rsdBcc.h" #include "rsdRuntime.h" -#include <bcinfo/bcinfo.h> +#include <bcinfo/MetadataExtractor.h> #include "rsContext.h" #include "rsScriptC.h" @@ -40,7 +40,7 @@ struct DrvScript { BCCScriptRef mBccScript; - struct BCScriptMetadata *mScriptMetadata; + bcinfo::MetadataExtractor *ME; InvokeFunc_t *mInvokeFunctions; void ** mFieldAddress; @@ -71,7 +71,9 @@ bool rsdScriptInit(const Context *rsc, pthread_mutex_lock(&rsdgInitMutex); char *cachePath = NULL; - struct BCScriptMetadata *md = NULL; + size_t exportFuncCount = 0; + size_t exportVarCount = 0; + size_t objectSlotCount = 0; DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript)); if (drv == NULL) { @@ -84,13 +86,13 @@ bool rsdScriptInit(const Context *rsc, drv->mScriptText = bitcode; drv->mScriptTextLength = bitcodeSize; - md = bcinfoGetScriptMetadata((const char*)drv->mScriptText, - drv->mScriptTextLength, 0); - if (!md) { + + drv->ME = new bcinfo::MetadataExtractor((const char*)drv->mScriptText, + drv->mScriptTextLength); + if (!drv->ME->extract()) { LOGE("bcinfo: failed to read script metadata"); goto error; } - drv->mScriptMetadata = md; //LOGE("mBccScript %p", script->mBccScript); @@ -112,7 +114,7 @@ bool rsdScriptInit(const Context *rsc, goto error; } - if (bccPrepareExecutableEx(drv->mBccScript, cacheDir, resName, 0) != 0) { + if (bccPrepareExecutable(drv->mBccScript, cacheDir, resName, 0) != 0) { LOGE("bcc: FAILS to prepare executable"); goto error; } @@ -122,40 +124,41 @@ bool rsdScriptInit(const Context *rsc, drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root")); drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init")); - if (md->exportFuncCount > 0) { - drv->mInvokeFunctions = (InvokeFunc_t*) calloc(md->exportFuncCount, + exportFuncCount = drv->ME->getExportFuncCount(); + if (exportFuncCount > 0) { + drv->mInvokeFunctions = (InvokeFunc_t*) calloc(exportFuncCount, sizeof(InvokeFunc_t)); - bccGetExportFuncList(drv->mBccScript, - md->exportFuncCount, + bccGetExportFuncList(drv->mBccScript, exportFuncCount, (void **) drv->mInvokeFunctions); } else { drv->mInvokeFunctions = NULL; } - if (md->exportVarCount > 0) { - drv->mFieldAddress = (void **) calloc(md->exportVarCount, - sizeof(void*)); - drv->mFieldIsObject = (bool *) calloc(md->exportVarCount, sizeof(bool)); - bccGetExportVarList(drv->mBccScript, - md->exportVarCount, + exportVarCount = drv->ME->getExportVarCount(); + if (exportVarCount > 0) { + drv->mFieldAddress = (void **) calloc(exportVarCount, sizeof(void*)); + drv->mFieldIsObject = (bool *) calloc(exportVarCount, sizeof(bool)); + bccGetExportVarList(drv->mBccScript, exportVarCount, (void **) drv->mFieldAddress); } else { drv->mFieldAddress = NULL; drv->mFieldIsObject = NULL; } - if (md->objectSlotCount) { - for (uint32_t ct=0; ct < md->objectSlotCount; ct++) { - drv->mFieldIsObject[md->objectSlotList[ct]] = true; + objectSlotCount = drv->ME->getObjectSlotCount(); + if (objectSlotCount > 0) { + const uint32_t *objectSlotList = drv->ME->getObjectSlotList(); + for (uint32_t ct=0; ct < objectSlotCount; ct++) { + drv->mFieldIsObject[objectSlotList[ct]] = true; } } // Copy info over to runtime - script->mHal.info.exportedFunctionCount = md->exportFuncCount; - script->mHal.info.exportedVariableCount = md->exportVarCount; - script->mHal.info.exportedPragmaCount = md->pragmaCount; - script->mHal.info.exportedPragmaKeyList = md->pragmaKeyList; - script->mHal.info.exportedPragmaValueList = md->pragmaValueList; + script->mHal.info.exportedFunctionCount = drv->ME->getExportFuncCount(); + script->mHal.info.exportedVariableCount = drv->ME->getExportVarCount(); + script->mHal.info.exportedPragmaCount = drv->ME->getPragmaCount(); + script->mHal.info.exportedPragmaKeyList = drv->ME->getPragmaKeyList(); + script->mHal.info.exportedPragmaValueList = drv->ME->getPragmaValueList(); script->mHal.info.root = drv->mRoot; pthread_mutex_unlock(&rsdgInitMutex); @@ -164,6 +167,10 @@ bool rsdScriptInit(const Context *rsc, error: pthread_mutex_unlock(&rsdgInitMutex); + if (drv->ME) { + delete drv->ME; + drv->ME = NULL; + } free(drv); return false; @@ -175,6 +182,7 @@ typedef struct { const Allocation * ain; Allocation * aout; const void * usr; + size_t usrLen; uint32_t mSliceSize; volatile int mSliceNum; @@ -202,6 +210,10 @@ typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint static void wc_xy(void *usr, uint32_t idx) { MTLaunchStruct *mtls = (MTLaunchStruct *)usr; + RsForEachStubParamStruct p; + memset(&p, 0, sizeof(p)); + p.usr = mtls->usr; + p.usr_len = mtls->usrLen; while (1) { uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); @@ -214,13 +226,15 @@ static void wc_xy(void *usr, uint32_t idx) { //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; + for (p.y = yStart; p.y < yEnd; p.y++) { + uint32_t offset = mtls->dimX * p.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); + for (p.x = mtls->xStart; p.x < mtls->xEnd; p.x++) { + p.in = xPtrIn; + p.out = xPtrOut; + ((rs_t)mtls->script->mHal.info.root) (p.in, p.out, p.usr, p.x, p.y, 0, 0); xPtrIn += mtls->eStrideIn; xPtrOut += mtls->eStrideOut; } @@ -230,6 +244,10 @@ static void wc_xy(void *usr, uint32_t idx) { static void wc_x(void *usr, uint32_t idx) { MTLaunchStruct *mtls = (MTLaunchStruct *)usr; + RsForEachStubParamStruct p; + memset(&p, 0, sizeof(p)); + p.usr = mtls->usr; + p.usr_len = mtls->usrLen; while (1) { uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); @@ -244,8 +262,10 @@ static void wc_x(void *usr, uint32_t idx) { //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); + for (p.x = xStart; p.x < xEnd; p.x++) { + p.in = xPtrIn; + p.out = xPtrOut; + ((rs_t)mtls->script->mHal.info.root) (p.in, p.out, p.usr, p.x, 0, 0, 0); xPtrIn += mtls->eStrideIn; xPtrOut += mtls->eStrideOut; } @@ -318,6 +338,7 @@ void rsdScriptInvokeForEach(const Context *rsc, mtls.aout = aout; mtls.script = s; mtls.usr = usr; + mtls.usrLen = usrLen; mtls.mSliceSize = 10; mtls.mSliceNum = 0; @@ -344,18 +365,25 @@ void rsdScriptInvokeForEach(const Context *rsc, //LOGE("launch 1"); } else { + RsForEachStubParamStruct p; + memset(&p, 0, sizeof(p)); + p.usr = mtls.usr; + p.usr_len = mtls.usrLen; + //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; + for (p.ar[0] = mtls.arrayStart; p.ar[0] < mtls.arrayEnd; p.ar[0]++) { + for (p.z = mtls.zStart; p.z < mtls.zEnd; p.z++) { + for (p.y = mtls.yStart; p.y < mtls.yEnd; p.y++) { + uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * p.ar[0] + + mtls.dimX * mtls.dimY * p.z + + mtls.dimX * p.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); + for (p.x = mtls.xStart; p.x < mtls.xEnd; p.x++) { + p.in = xPtrIn; + p.out = xPtrOut; + ((rs_t)s->mHal.info.root) (p.in, p.out, p.usr, p.x, p.y, p.z, p.ar[0]); xPtrIn += mtls.eStrideIn; xPtrOut += mtls.eStrideOut; } @@ -445,10 +473,10 @@ void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slo void rsdScriptDestroy(const Context *dc, Script *script) { DrvScript *drv = (DrvScript *)script->mHal.drv; - struct BCScriptMetadata *md = drv->mScriptMetadata; if (drv->mFieldAddress) { - for (size_t ct = 0; ct < md->exportVarCount; ct++) { + size_t exportVarCount = drv->ME->getExportVarCount(); + for (size_t ct = 0; ct < exportVarCount; ct++) { if (drv->mFieldIsObject[ct]) { // The field address can be NULL if the script-side has // optimized the corresponding global variable away. @@ -467,7 +495,8 @@ void rsdScriptDestroy(const Context *dc, Script *script) { drv->mInvokeFunctions = NULL; } - bcinfoReleaseScriptMetadata(&drv->mScriptMetadata); + delete drv->ME; + drv->ME = NULL; free(drv); script->mHal.drv = NULL; diff --git a/libs/rs/driver/rsdProgram.cpp b/libs/rs/driver/rsdProgram.cpp index 39b3805f5473..27a66639148b 100644 --- a/libs/rs/driver/rsdProgram.cpp +++ b/libs/rs/driver/rsdProgram.cpp @@ -44,6 +44,9 @@ bool rsdProgramVertexInit(const Context *rsc, const ProgramVertex *pv, static void SyncProgramConstants(const Context *rsc, const Program *p) { for (uint32_t ct=0; ct < p->mHal.state.texturesCount; ct++) { const Allocation *a = p->mHal.state.textures[ct].get(); + if (!a) { + continue; + } DrvAllocation *drvAlloc = (DrvAllocation *)a->mHal.drv; if (drvAlloc->uploadDeferred) { rsdAllocationSyncAll(rsc, a, RS_ALLOCATION_USAGE_SCRIPT); diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp index d8050ac7bdea..90c8928b2ebc 100644 --- a/libs/rs/driver/rsdRuntimeStubs.cpp +++ b/libs/rs/driver/rsdRuntimeStubs.cpp @@ -42,41 +42,6 @@ using namespace android::renderscript; // Allocation ////////////////////////////////////////////////////////////////////////////// -static uint32_t SC_allocGetDimX(Allocation *a) { - return a->mHal.state.dimensionX; -} - -static uint32_t SC_allocGetDimY(Allocation *a) { - return a->mHal.state.dimensionY; -} - -static uint32_t SC_allocGetDimZ(Allocation *a) { - return a->mHal.state.dimensionZ; -} - -static uint32_t SC_allocGetDimLOD(Allocation *a) { - return a->mHal.state.hasMipmaps; -} - -static uint32_t SC_allocGetDimFaces(Allocation *a) { - return a->mHal.state.hasFaces; -} - -static const void * SC_getElementAtX(Allocation *a, uint32_t x) { - const uint8_t *p = (const uint8_t *)a->getPtr(); - return &p[a->mHal.state.elementSizeBytes * x]; -} - -static const void * SC_getElementAtXY(Allocation *a, uint32_t x, uint32_t y) { - const uint8_t *p = (const uint8_t *)a->getPtr(); - return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX)]; -} - -static const void * SC_getElementAtXYZ(Allocation *a, uint32_t x, uint32_t y, uint32_t z) { - const uint8_t *p = (const uint8_t *)a->getPtr(); - return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX + - z * a->mHal.state.dimensionX * a->mHal.state.dimensionY)]; -} static void SC_AllocationSyncAll2(Allocation *a, RsAllocationUsageType source) { GET_TLS(); @@ -115,12 +80,6 @@ static void SC_AllocationCopy2DRange(Allocation *dstAlloc, } -const Allocation * SC_getAllocation(const void *ptr) { - GET_TLS(); - return rsrGetAllocation(rsc, sc, ptr); -} - - ////////////////////////////////////////////////////////////////////////////// // Context ////////////////////////////////////////////////////////////////////////////// @@ -599,18 +558,6 @@ static RsdSymbolTable gSyms[] = { { "_Z10rsIsObject7rs_font", (void *)&SC_IsObject, true }, // Allocation ops - { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX, true }, - { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY, true }, - { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ, true }, - { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD, true }, - { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces, true }, - - { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX, true }, - { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true }, - { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true }, - - { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation, true }, - { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_AllocationSyncAll, true }, { "_Z20rsgAllocationSyncAll13rs_allocation", (void *)&SC_AllocationSyncAll, false }, { "_Z20rsgAllocationSyncAll13rs_allocationj", (void *)&SC_AllocationSyncAll2, false }, diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp index 15cc4179dcc2..90fe4b237164 100644 --- a/libs/rs/driver/rsdShader.cpp +++ b/libs/rs/driver/rsdShader.cpp @@ -48,6 +48,7 @@ RsdShader::~RsdShader() { delete[] mAttribNames; delete[] mUniformNames; delete[] mUniformArraySizes; + delete[] mTextureTargets; } void RsdShader::initMemberVars() { @@ -59,6 +60,7 @@ void RsdShader::initMemberVars() { mAttribNames = NULL; mUniformNames = NULL; mUniformArraySizes = NULL; + mTextureTargets = NULL; mIsValid = false; } @@ -81,6 +83,7 @@ void RsdShader::init() { mUniformArraySizes[uniformCount] = 1; uniformCount++; } + } String8 RsdShader::getGLSLInputString() const { @@ -141,8 +144,10 @@ void RsdShader::appendTextures() { for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) { if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) { snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct); + mTextureTargets[ct] = GL_TEXTURE_2D; } else { snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct); + mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP; } mShader.append(buf); } @@ -400,9 +405,11 @@ void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) { for (uint32_t ct=0; ct < numTexturesToBind; ct++) { glActiveTexture(GL_TEXTURE0 + ct); + glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct); + if (!mRSProgram->mHal.state.textures[ct].get()) { - LOGE("No texture bound for shader id %u, texture unit %u", (uint)this, ct); - rsc->setError(RS_ERROR_BAD_SHADER, "No texture bound"); + // if nothing is bound, reset to default GL texture + glBindTexture(mTextureTargets[ct], 0); continue; } @@ -422,8 +429,6 @@ void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) { glTexParameteri(drvTex->glTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); rsdGLCheckError(rsc, "ProgramFragment::setup tex env"); } - - glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct); rsdGLCheckError(rsc, "ProgramFragment::setup uniforms"); } @@ -516,6 +521,11 @@ void RsdShader::initAttribAndUniformArray() { mUniformNames = new String8[mUniformCount]; mUniformArraySizes = new uint32_t[mUniformCount]; } + + mTextureCount = mRSProgram->mHal.state.texturesCount; + if (mTextureCount) { + mTextureTargets = new uint32_t[mTextureCount]; + } } void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix) { diff --git a/libs/rs/driver/rsdShader.h b/libs/rs/driver/rsdShader.h index 63c4231695de..3f0d6eae909e 100644 --- a/libs/rs/driver/rsdShader.h +++ b/libs/rs/driver/rsdShader.h @@ -84,6 +84,7 @@ protected: uint32_t mType; uint32_t mTextureCount; + uint32_t *mTextureTargets; uint32_t mAttribCount; uint32_t mUniformCount; android::String8 *mAttribNames; diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index 0dea97100d35..f27758249a5d 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -127,6 +127,7 @@ ObjDestroy { } ElementCreate { + direct param RsDataType mType param RsDataKind mKind param bool mNormalized @@ -135,6 +136,7 @@ ElementCreate { } ElementCreate2 { + direct param const RsElement * elements param const char ** names param const uint32_t * arraySize @@ -226,6 +228,7 @@ AllocationCopy2DRange { } SamplerCreate { + direct param RsSamplerValue magFilter param RsSamplerValue minFilter param RsSamplerValue wrapS @@ -311,6 +314,7 @@ ScriptCCreate { ProgramStoreCreate { + direct param bool colorMaskR param bool colorMaskG param bool colorMaskB @@ -324,6 +328,7 @@ ProgramStoreCreate { } ProgramRasterCreate { + direct param bool pointSmooth param bool lineSmooth param bool pointSprite @@ -352,12 +357,14 @@ ProgramBindSampler { } ProgramFragmentCreate { + direct param const char * shaderText param const uint32_t * params ret RsProgramFragment } ProgramVertexCreate { + direct param const char * shaderText param const uint32_t * params ret RsProgramVertex diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index f3e0c0a75291..a366d4985a48 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -58,6 +58,19 @@ void Allocation::updateCache() { } Allocation::~Allocation() { + if (mHal.state.hasReferences && + (mHal.state.hasFaces || mHal.state.hasMipmaps)) { + LOGE("Cube/mip allocation with references unsupported, memory not cleaned up!"); + } + + uint32_t elemCount = mHal.state.dimensionX; + if (mHal.state.dimensionY > 1) { + elemCount *= mHal.state.dimensionY; + } + if (mHal.state.dimensionZ > 1) { + elemCount *= mHal.state.dimensionZ; + } + decRefs(getPtr(), elemCount, 0); mRSC->mHal.funcs.allocation.destroy(mRSC, this); } @@ -239,6 +252,7 @@ Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) { Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT); alloc->setName(name.string(), name.size()); + type->decUserRef(); uint32_t count = dataSize / type->getElementSizeBytes(); @@ -270,6 +284,9 @@ 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 { + if (!mHal.state.hasReferences || !getIsScript()) { + return; + } const uint8_t *p = static_cast<const uint8_t *>(ptr); const Element *e = mHal.state.type->getElement(); uint32_t stride = e->getSizeBytes(); @@ -291,12 +308,12 @@ void Allocation::resize1D(Context *rsc, uint32_t dimX) { return; } - Type *t = mHal.state.type->cloneAndResize1D(rsc, dimX); + ObjectBaseRef<Type> t = mHal.state.type->cloneAndResize1D(rsc, dimX); if (dimX < oldDimX) { decRefs(getPtr(), oldDimX - dimX, dimX); } - rsc->mHal.funcs.allocation.resize(rsc, this, t, mHal.state.hasReferences); - mHal.state.type.set(t); + rsc->mHal.funcs.allocation.resize(rsc, this, t.get(), mHal.state.hasReferences); + mHal.state.type.set(t.get()); updateCache(); } diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h index f538dd13bf99..f2589c0b07ef 100644 --- a/libs/rs/rsAllocation.h +++ b/libs/rs/rsAllocation.h @@ -25,8 +25,16 @@ namespace renderscript { class Program; +/***************************************************************************** + * CAUTION + * + * Any layout changes for this class may require a corresponding change to be + * made to frameworks/compile/libbcc/lib/ScriptCRT/rs_core.c, which contains + * a partial copy of the information below. + * + *****************************************************************************/ class Allocation : public ObjectBase { - // The graphics equilivent of malloc. The allocation contains a structure of elements. + // The graphics equivalent of malloc. The allocation contains a structure of elements. public: struct Hal { diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp index e65febb4d464..ce06306a1ef0 100644 --- a/libs/rs/rsComponent.cpp +++ b/libs/rs/rsComponent.cpp @@ -176,36 +176,6 @@ bool Component::isReference() const { return (mType >= RS_TYPE_ELEMENT); } -String8 Component::getGLSLType() const { - if (mType == RS_TYPE_SIGNED_32) { - switch (mVectorSize) { - case 1: return String8("int"); - case 2: return String8("ivec2"); - case 3: return String8("ivec3"); - case 4: return String8("ivec4"); - } - } - if (mType == RS_TYPE_FLOAT_32) { - switch (mVectorSize) { - case 1: return String8("float"); - case 2: return String8("vec2"); - case 3: return String8("vec3"); - case 4: return String8("vec4"); - } - } - if ((mType == RS_TYPE_MATRIX_4X4) && (mVectorSize == 1)) { - return String8("mat4"); - } - if ((mType == RS_TYPE_MATRIX_3X3) && (mVectorSize == 1)) { - return String8("mat3"); - } - if ((mType == RS_TYPE_MATRIX_2X2) && (mVectorSize == 1)) { - return String8("mat2"); - } - return String8(); -} - - static const char * gTypeBasicStrings[] = { "NONE", "F16", diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h index a448f0e8f495..6ddc990b2486 100644 --- a/libs/rs/rsComponent.h +++ b/libs/rs/rsComponent.h @@ -32,10 +32,8 @@ public: void set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize=1); - String8 getGLSLType() const; void dumpLOGV(const char *prefix) const; - RsDataType getType() const {return mType;} RsDataKind getKind() const {return mKind;} bool getIsNormalized() const {return mNormalized;} diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index decd9f1826a9..f65dd4723a81 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -240,25 +240,38 @@ void * Context::threadProc(void *vrsc) { rsc->setProgramStore(NULL); rsc->mStateFont.init(rsc); rsc->setFont(NULL); + rsc->mStateSampler.init(rsc); rsc->mFBOCache.init(rsc); } rsc->mRunning = true; bool mDraw = true; + bool doWait = true; + + uint64_t targetTime = rsc->getTime(); while (!rsc->mExit) { - mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw); + uint64_t waitTime = 0; + uint64_t now = rsc->getTime(); + if (now < targetTime) { + waitTime = targetTime - now; + } else { + doWait = false; + } + + mDraw |= rsc->mIO.playCoreCommands(rsc, doWait, waitTime); mDraw &= (rsc->mRootScript.get() != NULL); mDraw &= rsc->mHasSurface; - uint32_t targetTime = 0; if (mDraw && rsc->mIsGraphicsContext) { - targetTime = rsc->runRootScript(); + uint64_t delay = rsc->runRootScript() * 1000000; + targetTime = rsc->getTime() + delay; + doWait = delay != 0; if (rsc->props.mLogVisual) { rsc->displayDebugStats(); } - mDraw = targetTime && !rsc->mPaused; + mDraw = !rsc->mPaused; rsc->timerSet(RS_TIMER_CLEAR_SWAP); rsc->mHal.funcs.swap(rsc); rsc->timerFrame(); @@ -266,12 +279,6 @@ void * Context::threadProc(void *vrsc) { rsc->timerPrint(); rsc->timerReset(); } - if (targetTime > 1) { - int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000; - if (t > 0) { - usleep(t); - } - } } LOGV("%p, RS Thread exiting", rsc); @@ -301,6 +308,7 @@ void Context::destroyWorkerThreadResources() { mStateFragment.deinit(this); mStateFragmentStore.deinit(this); mStateFont.deinit(this); + mStateSampler.deinit(this); mFBOCache.deinit(this); } //LOGV("destroyWorkerThreadResources 2"); @@ -333,6 +341,7 @@ Context::Context() { mPaused = false; mObjHead = NULL; mError = RS_ERROR_NONE; + mTargetSdkVersion = 14; mDPI = 96; mIsContextLite = false; } @@ -678,19 +687,25 @@ void rsi_ContextDeinitToClient(Context *rsc) { } } -RsContext rsContextCreate(RsDevice vdev, uint32_t version) { +RsContext rsContextCreate(RsDevice vdev, uint32_t version, + uint32_t sdkVersion) { LOGV("rsContextCreate %p", vdev); Device * dev = static_cast<Device *>(vdev); Context *rsc = Context::createContext(dev, NULL); + if (rsc) { + rsc->setTargetSdkVersion(sdkVersion); + } return rsc; } RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, - RsSurfaceConfig sc, uint32_t dpi) { + uint32_t sdkVersion, RsSurfaceConfig sc, + uint32_t dpi) { LOGV("rsContextCreateGL %p", vdev); Device * dev = static_cast<Device *>(vdev); Context *rsc = Context::createContext(dev, &sc); if (rsc) { + rsc->setTargetSdkVersion(sdkVersion); rsc->setDPI(dpi); } LOGV("rsContextCreateGL ret %p ", rsc); diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h index 309fe9532bba..3c7a3d236eac 100644 --- a/libs/rs/rsContext.h +++ b/libs/rs/rsContext.h @@ -199,9 +199,13 @@ public: uint32_t getDPI() const {return mDPI;} void setDPI(uint32_t dpi) {mDPI = dpi;} + uint32_t getTargetSdkVersion() const {return mTargetSdkVersion;} + void setTargetSdkVersion(uint32_t sdkVer) {mTargetSdkVersion = sdkVer;} + Device *mDev; protected: + uint32_t mTargetSdkVersion; uint32_t mDPI; uint32_t mWidth; uint32_t mHeight; diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp index b77b18a0b686..36bbdf05a48c 100644 --- a/libs/rs/rsElement.cpp +++ b/libs/rs/rsElement.cpp @@ -29,13 +29,16 @@ Element::Element(Context *rsc) : ObjectBase(rsc) { } Element::~Element() { + clear(); +} + +void Element::preDestroy() const { for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) { if (mRSC->mStateElement.mElements[ct] == this) { mRSC->mStateElement.mElements.removeAt(ct); break; } } - clear(); } void Element::clear() { @@ -60,6 +63,7 @@ size_t Element::getSizeBits() const { void Element::dumpLOGV(const char *prefix) const { ObjectBase::dumpLOGV(prefix); LOGV("%s Element: fieldCount: %zu, size bytes: %zu", prefix, mFieldCount, getSizeBytes()); + mComponent.dumpLOGV(prefix); for (uint32_t ct = 0; ct < mFieldCount; ct++) { LOGV("%s Element field index: %u ------------------", prefix, ct); LOGV("%s name: %s, offsetBits: %u, arraySize: %u", @@ -97,60 +101,46 @@ Element *Element::createFromStream(Context *rsc, IStream *stream) { String8 name; stream->loadString(&name); - Element *elem = new Element(rsc); - elem->mComponent.loadFromStream(stream); - - elem->mFieldCount = stream->loadU32(); - if (elem->mFieldCount) { - elem->mFields = new ElementField_t [elem->mFieldCount]; - for (uint32_t ct = 0; ct < elem->mFieldCount; ct ++) { - stream->loadString(&elem->mFields[ct].name); - elem->mFields[ct].arraySize = stream->loadU32(); - Element *fieldElem = Element::createFromStream(rsc, stream); - elem->mFields[ct].e.set(fieldElem); - } - } + Component component; + component.loadFromStream(stream); - // We need to check if this already exists - for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { - Element *ee = rsc->mStateElement.mElements[ct]; - if (ee->isEqual(elem)) { - ObjectBase::checkDelete(elem); - ee->incUserRef(); - return ee; - } + uint32_t fieldCount = stream->loadU32(); + if (!fieldCount) { + return (Element *)Element::create(rsc, + component.getType(), + component.getKind(), + component.getIsNormalized(), + component.getVectorSize());; } - elem->compute(); - rsc->mStateElement.mElements.push(elem); - return elem; -} - -bool Element::isEqual(const Element *other) const { - if (other == NULL) { - return false; + const Element **subElems = new const Element *[fieldCount]; + const char **subElemNames = new const char *[fieldCount]; + size_t *subElemNamesLengths = new size_t[fieldCount]; + uint32_t *arraySizes = new uint32_t[fieldCount]; + + String8 elemName; + for (uint32_t ct = 0; ct < fieldCount; ct ++) { + stream->loadString(&elemName); + subElemNamesLengths[ct] = elemName.length(); + char *tmpName = new char[subElemNamesLengths[ct]]; + memcpy(tmpName, elemName.string(), subElemNamesLengths[ct]); + subElemNames[ct] = tmpName; + arraySizes[ct] = stream->loadU32(); + subElems[ct] = Element::createFromStream(rsc, stream); } - if (!other->getFieldCount() && !mFieldCount) { - if ((other->getType() == getType()) && - (other->getKind() == getKind()) && - (other->getComponent().getIsNormalized() == getComponent().getIsNormalized()) && - (other->getComponent().getVectorSize() == getComponent().getVectorSize())) { - return true; - } - return false; - } - if (other->getFieldCount() == mFieldCount) { - for (uint32_t i=0; i < mFieldCount; i++) { - if ((!other->mFields[i].e->isEqual(mFields[i].e.get())) || - (other->mFields[i].name.length() != mFields[i].name.length()) || - (other->mFields[i].name != mFields[i].name) || - (other->mFields[i].arraySize != mFields[i].arraySize)) { - return false; - } - } - return true; + + const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames, + subElemNamesLengths, arraySizes); + for (uint32_t ct = 0; ct < fieldCount; ct ++) { + delete [] subElemNames[ct]; + subElems[ct]->decUserRef(); } - return false; + delete[] subElems; + delete[] subElemNames; + delete[] subElemNamesLengths; + delete[] arraySizes; + + return (Element *)elem; } void Element::compute() { @@ -172,9 +162,11 @@ void Element::compute() { } -const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk, +ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk, bool isNorm, uint32_t vecSize) { + ObjectBaseRef<const Element> returnRef; // Look for an existing match. + ObjectBase::asyncLock(); for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { const Element *ee = rsc->mStateElement.mElements[ct]; if (!ee->getFieldCount() && @@ -183,21 +175,31 @@ const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk, (ee->getComponent().getIsNormalized() == isNorm) && (ee->getComponent().getVectorSize() == vecSize)) { // Match - ee->incUserRef(); + returnRef.set(ee); + ObjectBase::asyncUnlock(); return ee; } } + ObjectBase::asyncUnlock(); Element *e = new Element(rsc); + returnRef.set(e); e->mComponent.set(dt, dk, isNorm, vecSize); e->compute(); + + ObjectBase::asyncLock(); rsc->mStateElement.mElements.push(e); - return e; + ObjectBase::asyncUnlock(); + + return returnRef; } -const Element * Element::create(Context *rsc, size_t count, const Element **ein, +ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein, const char **nin, const size_t * lengths, const uint32_t *asin) { + + ObjectBaseRef<const Element> returnRef; // Look for an existing match. + ObjectBase::asyncLock(); for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) { const Element *ee = rsc->mStateElement.mElements[ct]; if (ee->getFieldCount() == count) { @@ -212,13 +214,16 @@ const Element * Element::create(Context *rsc, size_t count, const Element **ein, } } if (match) { - ee->incUserRef(); - return ee; + returnRef.set(ee); + ObjectBase::asyncUnlock(); + return returnRef; } } } + ObjectBase::asyncUnlock(); Element *e = new Element(rsc); + returnRef.set(e); e->mFields = new ElementField_t [count]; e->mFieldCount = count; for (size_t ct=0; ct < count; ct++) { @@ -228,26 +233,11 @@ const Element * Element::create(Context *rsc, size_t count, const Element **ein, } e->compute(); + ObjectBase::asyncLock(); rsc->mStateElement.mElements.push(e); - return e; -} - -String8 Element::getGLSLType(uint32_t indent) const { - String8 s; - for (uint32_t ct=0; ct < indent; ct++) { - s.append(" "); - } + ObjectBase::asyncUnlock(); - if (!mFieldCount) { - // Basic component. - s.append(mComponent.getGLSLType()); - } else { - rsAssert(0); - //s.append("struct "); - //s.append(getCStructBody(indent)); - } - - return s; + return returnRef; } void Element::incRefs(const void *ptr) const { @@ -294,6 +284,23 @@ void Element::decRefs(const void *ptr) const { } } +void Element::Builder::add(const Element *e, const char *nameStr, uint32_t arraySize) { + mBuilderElementRefs.push(ObjectBaseRef<const Element>(e)); + mBuilderElements.push(e); + mBuilderNameStrings.push(nameStr); + mBuilderNameLengths.push(strlen(nameStr)); + mBuilderArrays.push(arraySize); + +} + +ObjectBaseRef<const Element> Element::Builder::create(Context *rsc) { + return Element::createRef(rsc, mBuilderElements.size(), + &(mBuilderElements.editArray()[0]), + &(mBuilderNameStrings.editArray()[0]), + mBuilderNameLengths.editArray(), + mBuilderArrays.editArray()); +} + ElementState::ElementState() { const uint32_t initialCapacity = 32; @@ -324,10 +331,10 @@ void ElementState::elementBuilderAdd(const Element *e, const char *nameStr, uint const Element *ElementState::elementBuilderCreate(Context *rsc) { return Element::create(rsc, mBuilderElements.size(), - &(mBuilderElements.editArray()[0]), - &(mBuilderNameStrings.editArray()[0]), - mBuilderNameLengths.editArray(), - mBuilderArrays.editArray()); + &(mBuilderElements.editArray()[0]), + &(mBuilderNameStrings.editArray()[0]), + mBuilderNameLengths.editArray(), + mBuilderArrays.editArray()); } @@ -342,9 +349,7 @@ RsElement rsi_ElementCreate(Context *rsc, RsDataKind dk, bool norm, uint32_t vecSize) { - const Element *e = Element::create(rsc, dt, dk, norm, vecSize); - e->incUserRef(); - return (RsElement)e; + return (RsElement)Element::create(rsc, dt, dk, norm, vecSize); } @@ -358,15 +363,15 @@ RsElement rsi_ElementCreate2(Context *rsc, const uint32_t * arraySizes, size_t arraySizes_length) { - const Element *e = Element::create(rsc, ein_length, (const Element **)ein, names, nameLengths, arraySizes); - e->incUserRef(); - return (RsElement)e; + return (RsElement)Element::create(rsc, ein_length, (const Element **)ein, + names, nameLengths, arraySizes); } } } -void rsaElementGetNativeData(RsContext con, RsElement elem, uint32_t *elemData, uint32_t elemDataSize) { +void rsaElementGetNativeData(RsContext con, RsElement elem, + uint32_t *elemData, uint32_t elemDataSize) { rsAssert(elemDataSize == 5); // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements Element *e = static_cast<Element *>(elem); @@ -378,7 +383,8 @@ void rsaElementGetNativeData(RsContext con, RsElement elem, uint32_t *elemData, (*elemData++) = e->getFieldCount(); } -void rsaElementGetSubElements(RsContext con, RsElement elem, uint32_t *ids, const char **names, uint32_t dataSize) { +void rsaElementGetSubElements(RsContext con, RsElement elem, uint32_t *ids, + const char **names, uint32_t dataSize) { Element *e = static_cast<Element *>(elem); rsAssert(e->getFieldCount() == dataSize); diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h index 26e2760c124b..c3ef25038d33 100644 --- a/libs/rs/rsElement.h +++ b/libs/rs/rsElement.h @@ -28,8 +28,17 @@ namespace renderscript { // An element is a group of Components that occupies one cell in a structure. class Element : public ObjectBase { public: - ~Element(); - + class Builder { + public: + void add(const Element *e, const char *nameStr, uint32_t arraySize); + ObjectBaseRef<const Element> create(Context *rsc); + private: + Vector<ObjectBaseRef<const Element> > mBuilderElementRefs; + Vector<const Element *> mBuilderElements; + Vector<const char*> mBuilderNameStrings; + Vector<size_t> mBuilderNameLengths; + Vector<uint32_t> mBuilderArrays; + }; uint32_t getGLType() const; uint32_t getGLFormat() const; @@ -55,24 +64,45 @@ public: RsDataKind getKind() const {return mComponent.getKind();} uint32_t getBits() const {return mBits;} - String8 getGLSLType(uint32_t indent=0) const; - void dumpLOGV(const char *prefix) const; virtual void serialize(OStream *stream) const; virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ELEMENT; } static Element *createFromStream(Context *rsc, IStream *stream); - static const Element * create(Context *rsc, RsDataType dt, RsDataKind dk, - bool isNorm, uint32_t vecSize); - static const Element * create(Context *rsc, size_t count, const Element **, - const char **, const size_t * lengths, const uint32_t *asin); + static ObjectBaseRef<const Element> createRef(Context *rsc, + RsDataType dt, + RsDataKind dk, + bool isNorm, + uint32_t vecSize); + static ObjectBaseRef<const Element> createRef(Context *rsc, size_t count, + const Element **, + const char **, + const size_t * lengths, + const uint32_t *asin); + + static const Element* create(Context *rsc, + RsDataType dt, + RsDataKind dk, + bool isNorm, + uint32_t vecSize) { + ObjectBaseRef<const Element> elem = createRef(rsc, dt, dk, isNorm, vecSize); + elem->incUserRef(); + return elem.get(); + } + static const Element* create(Context *rsc, size_t count, + const Element **ein, + const char **nin, + const size_t * lengths, + const uint32_t *asin) { + ObjectBaseRef<const Element> elem = createRef(rsc, count, ein, nin, lengths, asin); + elem->incUserRef(); + return elem.get(); + } void incRefs(const void *) const; void decRefs(const void *) const; bool getHasReferences() const {return mHasReference;} - bool isEqual(const Element *other) const; - protected: // deallocate any components that are part of this element. void clear(); @@ -88,12 +118,15 @@ protected: bool mHasReference; + virtual ~Element(); Element(Context *); Component mComponent; uint32_t mBits; void compute(); + + virtual void preDestroy() const; }; diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp index cd02c24b981f..df5dc128061b 100644 --- a/libs/rs/rsFileA3D.cpp +++ b/libs/rs/rsFileA3D.cpp @@ -68,7 +68,7 @@ void FileA3D::parseHeader(IStream *headerStream) { for (uint32_t i = 0; i < numIndexEntries; i ++) { A3DIndexEntry *entry = new A3DIndexEntry(); headerStream->loadString(&entry->mObjectName); - LOGV("Header data, entry name = %s", entry->mObjectName.string()); + //LOGV("Header data, entry name = %s", entry->mObjectName.string()); entry->mType = (RsA3DClassID)headerStream->loadU32(); if (mUse64BitOffsets){ entry->mOffset = headerStream->loadOffset(); @@ -369,7 +369,7 @@ RsObjectBase rsaFileA3DGetEntryByIndex(RsContext con, uint32_t index, RsFile fil } ObjectBase *obj = fa3d->initializeFromEntry(index); - LOGV("Returning object with name %s", obj->getName()); + //LOGV("Returning object with name %s", obj->getName()); return obj; } diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp index ce674f420b11..7efed9d9f948 100644 --- a/libs/rs/rsFont.cpp +++ b/libs/rs/rsFont.cpp @@ -490,49 +490,47 @@ void FontState::initRenderState() { shaderString.append(" gl_FragColor = col;\n"); shaderString.append("}\n"); - const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); - const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); - mRSC->mStateElement.elementBuilderBegin(); - mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); - mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); - const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); + ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); + ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); + Element::Builder builder; + builder.add(colorElem.get(), "Color", 1); + builder.add(gammaElem.get(), "Gamma", 1); + ObjectBaseRef<const Element> constInput = builder.create(mRSC); - Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); + ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1, 0, 0, false, false); uint32_t tmp[4]; tmp[0] = RS_PROGRAM_PARAM_CONSTANT; - tmp[1] = (uint32_t)inputType; + tmp[1] = (uint32_t)inputType.get(); tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; tmp[3] = RS_TEXTURE_2D; - mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType, + mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType.get(), RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), shaderString.length(), tmp, 4); mFontShaderF.set(pf); mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); - Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, - RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); - mFontSampler.set(sampler); - mFontShaderF->bindSampler(mRSC, 0, sampler); - - ProgramStore *fontStore = new ProgramStore(mRSC, true, true, true, true, - false, false, - RS_BLEND_SRC_SRC_ALPHA, - RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, - RS_DEPTH_FUNC_ALWAYS); - mFontProgramStore.set(fontStore); + mFontSampler.set(Sampler::getSampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, + RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP).get()); + mFontShaderF->bindSampler(mRSC, 0, mFontSampler.get()); + + mFontProgramStore.set(ProgramStore::getProgramStore(mRSC, true, true, true, true, + false, false, + RS_BLEND_SRC_SRC_ALPHA, + RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, + RS_DEPTH_FUNC_ALWAYS).get()); mFontProgramStore->init(); } void FontState::initTextTexture() { - const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); + ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); // We will allocate a texture to initially hold 32 character bitmaps - Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); + ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), 1024, 256, 0, false, false); - Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType, + Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType.get(), RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); mTextTexture.set(cacheAlloc); mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); @@ -557,11 +555,11 @@ void FontState::initTextTexture() { // Avoid having to reallocate memory and render quad by quad void FontState::initVertexArrayBuffers() { // Now lets write index data - const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); + ObjectBaseRef<const Element> indexElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); uint32_t numIndicies = mMaxNumberOfQuads * 6; - Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); + ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), numIndicies, 0, 0, false, false); - Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType, + Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType.get(), RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); @@ -582,19 +580,19 @@ void FontState::initVertexArrayBuffers() { indexAlloc->sendDirty(mRSC); - const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); - const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); + ObjectBaseRef<const Element> posElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); + ObjectBaseRef<const Element> texElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); - mRSC->mStateElement.elementBuilderBegin(); - mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); - mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); - const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); + Element::Builder builder; + builder.add(posElem.get(), "position", 1); + builder.add(texElem.get(), "texture0", 1); + ObjectBaseRef<const Element> vertexDataElem = builder.create(mRSC); - Type *vertexDataType = Type::getType(mRSC, vertexDataElem, - mMaxNumberOfQuads * 4, - 0, 0, false, false); + ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(), + mMaxNumberOfQuads * 4, + 0, 0, false, false); - Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType, + Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType.get(), RS_ALLOCATION_USAGE_SCRIPT); mTextMeshPtr = (float*)vertexAlloc->getPtr(); @@ -735,7 +733,7 @@ void FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, Font *currentFont = mRSC->getFont(); if (!currentFont) { if (!mDefault.get()) { - String8 fontsDir("/fonts/DroidSans.ttf"); + String8 fontsDir("/fonts/Roboto-Regular.ttf"); String8 fullPath(getenv("ANDROID_ROOT")); fullPath += fontsDir; diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h index b0e1430e228b..679591ca434f 100644 --- a/libs/rs/rsFont.h +++ b/libs/rs/rsFont.h @@ -146,7 +146,6 @@ public: void deinit(Context *rsc); ObjectBaseRef<Font> mDefault; - ObjectBaseRef<Font> mLast; void renderText(const char *text, uint32_t len, int32_t x, int32_t y, uint32_t startIndex = 0, int numGlyphs = -1, diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp index 7023a1ff2863..02a76ab027d2 100644 --- a/libs/rs/rsLocklessFifo.cpp +++ b/libs/rs/rsLocklessFifo.cpp @@ -129,21 +129,23 @@ void LocklessCommandFifo::flush() { //dumpState("flush 2"); } -void LocklessCommandFifo::wait() { +bool LocklessCommandFifo::wait(uint64_t timeout) { while (isEmpty() && !mInShutdown) { mSignalToControl.set(); - mSignalToWorker.wait(); + return mSignalToWorker.wait(timeout); } + return true; } -const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData) { +const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData, uint64_t timeout) { while (1) { //dumpState("get"); - wait(); - if (mInShutdown) { + wait(timeout); + + if (isEmpty() || mInShutdown) { *command = 0; *bytesData = 0; - return 0; + return NULL; } *command = reinterpret_cast<const uint16_t *>(mGet)[0]; diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h index eabdc3e97f05..4962ef614cc0 100644 --- a/libs/rs/rsLocklessFifo.h +++ b/libs/rs/rsLocklessFifo.h @@ -57,9 +57,9 @@ public: void commitSync(uint32_t command, uint32_t bytes); void flush(); - void wait(); + bool wait(uint64_t timeout = 0); - const void * get(uint32_t *command, uint32_t *bytesData); + const void * get(uint32_t *command, uint32_t *bytesData, uint64_t timeout = 0); void next(); void makeSpace(uint32_t bytes); diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h index 01850f1e2511..c7cfb0e2e8b0 100644 --- a/libs/rs/rsObjectBase.h +++ b/libs/rs/rsObjectBase.h @@ -114,7 +114,10 @@ public: } ObjectBaseRef & operator= (const ObjectBaseRef &ref) { - return ObjectBaseRef(ref); + if (&ref != this) { + set(ref); + } + return *this; } ~ObjectBaseRef() { diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp index b1d8f48b9ee3..33eb422e3354 100644 --- a/libs/rs/rsProgram.cpp +++ b/libs/rs/rsProgram.cpp @@ -116,7 +116,7 @@ void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) { rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation"); return; } - if (!alloc->getType()->isEqual(mHal.state.constantTypes[slot].get())) { + if (alloc->getType() != mHal.state.constantTypes[slot].get()) { LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch", slot, (uint32_t)this); rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation"); diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp index 356ff778f126..ff2952051162 100644 --- a/libs/rs/rsProgramFragment.cpp +++ b/libs/rs/rsProgramFragment.cpp @@ -97,18 +97,18 @@ void ProgramFragmentState::init(Context *rsc) { shaderString.append(" gl_FragColor = col;\n"); shaderString.append("}\n"); - const Element *colorElem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); - rsc->mStateElement.elementBuilderBegin(); - rsc->mStateElement.elementBuilderAdd(colorElem, "Color", 1); - const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc); + ObjectBaseRef<const Element> colorElem = Element::createRef(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); + Element::Builder builder; + builder.add(colorElem.get(), "Color", 1); + ObjectBaseRef<const Element> constInput = builder.create(rsc); - Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false); + ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false); uint32_t tmp[2]; tmp[0] = RS_PROGRAM_PARAM_CONSTANT; - tmp[1] = (uint32_t)inputType; + tmp[1] = (uint32_t)inputType.get(); - Allocation *constAlloc = Allocation::createAllocation(rsc, inputType, + Allocation *constAlloc = Allocation::createAllocation(rsc, inputType.get(), RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS); ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(), shaderString.length(), tmp, 2); diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp index 435561d7308a..945b5eca68fd 100644 --- a/libs/rs/rsProgramRaster.cpp +++ b/libs/rs/rsProgramRaster.cpp @@ -37,6 +37,15 @@ ProgramRaster::ProgramRaster(Context *rsc, bool pointSmooth, rsc->mHal.funcs.raster.init(rsc, this); } +void ProgramRaster::preDestroy() const { + for (uint32_t ct = 0; ct < mRSC->mStateRaster.mRasterPrograms.size(); ct++) { + if (mRSC->mStateRaster.mRasterPrograms[ct] == this) { + mRSC->mStateRaster.mRasterPrograms.removeAt(ct); + break; + } + } +} + ProgramRaster::~ProgramRaster() { mRSC->mHal.funcs.raster.destroy(mRSC, this); } @@ -65,8 +74,8 @@ ProgramRasterState::~ProgramRasterState() { } void ProgramRasterState::init(Context *rsc) { - ProgramRaster *pr = new ProgramRaster(rsc, false, false, false, 1.f, RS_CULL_BACK); - mDefault.set(pr); + mDefault.set(ProgramRaster::getProgramRaster(rsc, false, false, + false, 1.f, RS_CULL_BACK).get()); } void ProgramRasterState::deinit(Context *rsc) { @@ -74,19 +83,47 @@ void ProgramRasterState::deinit(Context *rsc) { mLast.clear(); } -namespace android { -namespace renderscript { +ObjectBaseRef<ProgramRaster> ProgramRaster::getProgramRaster(Context *rsc, + bool pointSmooth, + bool lineSmooth, + bool pointSprite, + float lineWidth, + RsCullMode cull) { + ObjectBaseRef<ProgramRaster> returnRef; + ObjectBase::asyncLock(); + for (uint32_t ct = 0; ct < rsc->mStateRaster.mRasterPrograms.size(); ct++) { + ProgramRaster *existing = rsc->mStateRaster.mRasterPrograms[ct]; + if (existing->mHal.state.pointSmooth != pointSmooth) continue; + if (existing->mHal.state.lineSmooth != lineSmooth) continue; + if (existing->mHal.state.pointSprite != pointSprite) continue; + if (existing->mHal.state.lineWidth != lineWidth) continue; + if (existing->mHal.state.cull != cull) continue; + returnRef.set(existing); + ObjectBase::asyncUnlock(); + return returnRef; + } + ObjectBase::asyncUnlock(); -RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, - bool pointSmooth, - bool lineSmooth, - bool pointSprite, - float lineWidth, - RsCullMode cull) { ProgramRaster *pr = new ProgramRaster(rsc, pointSmooth, lineSmooth, pointSprite, lineWidth, cull); + returnRef.set(pr); + + ObjectBase::asyncLock(); + rsc->mStateRaster.mRasterPrograms.push(pr); + ObjectBase::asyncUnlock(); + + return returnRef; +} + +namespace android { +namespace renderscript { + +RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSmooth, bool lineSmooth, + bool pointSprite, float lineWidth, RsCullMode cull) { + ObjectBaseRef<ProgramRaster> pr = ProgramRaster::getProgramRaster(rsc, pointSmooth, lineSmooth, + pointSprite, lineWidth, cull); pr->incUserRef(); - return pr; + return pr.get(); } } diff --git a/libs/rs/rsProgramRaster.h b/libs/rs/rsProgramRaster.h index efdb94874197..09d7d5432c9a 100644 --- a/libs/rs/rsProgramRaster.h +++ b/libs/rs/rsProgramRaster.h @@ -27,19 +27,17 @@ class ProgramRasterState; class ProgramRaster : public ProgramBase { public: - ProgramRaster(Context *rsc, - bool pointSmooth, - bool lineSmooth, - bool pointSprite, - float lineWidth, - RsCullMode cull); - virtual ~ProgramRaster(); - virtual void setup(const Context *, ProgramRasterState *); virtual void serialize(OStream *stream) const; virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_RASTER; } static ProgramRaster *createFromStream(Context *rsc, IStream *stream); + static ObjectBaseRef<ProgramRaster> getProgramRaster(Context *rsc, + bool pointSmooth, + bool lineSmooth, + bool pointSprite, + float lineWidth, + RsCullMode cull); struct Hal { mutable void *drv; @@ -55,6 +53,17 @@ public: Hal mHal; protected: + virtual void preDestroy() const; + virtual ~ProgramRaster(); + +private: + ProgramRaster(Context *rsc, + bool pointSmooth, + bool lineSmooth, + bool pointSprite, + float lineWidth, + RsCullMode cull); + }; class ProgramRasterState { @@ -66,6 +75,9 @@ public: ObjectBaseRef<ProgramRaster> mDefault; ObjectBaseRef<ProgramRaster> mLast; + + // Cache of all existing raster programs. + Vector<ProgramRaster *> mRasterPrograms; }; diff --git a/libs/rs/rsProgramStore.cpp b/libs/rs/rsProgramStore.cpp index 8fe890becb72..7e25a226d8ae 100644 --- a/libs/rs/rsProgramStore.cpp +++ b/libs/rs/rsProgramStore.cpp @@ -41,6 +41,15 @@ ProgramStore::ProgramStore(Context *rsc, mHal.state.depthFunc = depthFunc; } +void ProgramStore::preDestroy() const { + for (uint32_t ct = 0; ct < mRSC->mStateFragmentStore.mStorePrograms.size(); ct++) { + if (mRSC->mStateFragmentStore.mStorePrograms[ct] == this) { + mRSC->mStateFragmentStore.mStorePrograms.removeAt(ct); + break; + } + } +} + ProgramStore::~ProgramStore() { mRSC->mHal.funcs.store.destroy(mRSC, this); } @@ -71,14 +80,58 @@ ProgramStoreState::ProgramStoreState() { ProgramStoreState::~ProgramStoreState() { } +ObjectBaseRef<ProgramStore> ProgramStore::getProgramStore(Context *rsc, + bool colorMaskR, + bool colorMaskG, + bool colorMaskB, + bool colorMaskA, + bool depthMask, bool ditherEnable, + RsBlendSrcFunc srcFunc, + RsBlendDstFunc destFunc, + RsDepthFunc depthFunc) { + ObjectBaseRef<ProgramStore> returnRef; + ObjectBase::asyncLock(); + for (uint32_t ct = 0; ct < rsc->mStateFragmentStore.mStorePrograms.size(); ct++) { + ProgramStore *existing = rsc->mStateFragmentStore.mStorePrograms[ct]; + if (existing->mHal.state.ditherEnable != ditherEnable) continue; + if (existing->mHal.state.colorRWriteEnable != colorMaskR) continue; + if (existing->mHal.state.colorGWriteEnable != colorMaskG) continue; + if (existing->mHal.state.colorBWriteEnable != colorMaskB) continue; + if (existing->mHal.state.colorAWriteEnable != colorMaskA) continue; + if (existing->mHal.state.blendSrc != srcFunc) continue; + if (existing->mHal.state.blendDst != destFunc) continue; + if (existing->mHal.state.depthWriteEnable != depthMask) continue; + if (existing->mHal.state.depthFunc != depthFunc) continue; + + returnRef.set(existing); + ObjectBase::asyncUnlock(); + return returnRef; + } + ObjectBase::asyncUnlock(); + + ProgramStore *pfs = new ProgramStore(rsc, + colorMaskR, colorMaskG, colorMaskB, colorMaskA, + depthMask, ditherEnable, + srcFunc, destFunc, depthFunc); + returnRef.set(pfs); + + pfs->init(); + + ObjectBase::asyncLock(); + rsc->mStateFragmentStore.mStorePrograms.push(pfs); + ObjectBase::asyncUnlock(); + + return returnRef; +} + + + void ProgramStoreState::init(Context *rsc) { - ProgramStore *ps = new ProgramStore(rsc, - true, true, true, true, - true, true, - RS_BLEND_SRC_ONE, RS_BLEND_DST_ZERO, - RS_DEPTH_FUNC_LESS); - ps->init(); - mDefault.set(ps); + mDefault.set(ProgramStore::getProgramStore(rsc, + true, true, true, true, + true, true, + RS_BLEND_SRC_ONE, RS_BLEND_DST_ZERO, + RS_DEPTH_FUNC_LESS).get()); } void ProgramStoreState::deinit(Context *rsc) { @@ -96,13 +149,14 @@ RsProgramStore rsi_ProgramStoreCreate(Context *rsc, RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc, RsDepthFunc depthFunc) { - ProgramStore *pfs = new ProgramStore(rsc, - colorMaskR, colorMaskG, colorMaskB, colorMaskA, - depthMask, ditherEnable, - srcFunc, destFunc, depthFunc); - pfs->init(); - pfs->incUserRef(); - return pfs; + + ObjectBaseRef<ProgramStore> ps = ProgramStore::getProgramStore(rsc, + colorMaskR, colorMaskG, + colorMaskB, colorMaskA, + depthMask, ditherEnable, + srcFunc, destFunc, depthFunc); + ps->incUserRef(); + return ps.get(); } } diff --git a/libs/rs/rsProgramStore.h b/libs/rs/rsProgramStore.h index 77b3881fc8ee..e21f039678b3 100644 --- a/libs/rs/rsProgramStore.h +++ b/libs/rs/rsProgramStore.h @@ -28,18 +28,17 @@ class ProgramStoreState; class ProgramStore : public ProgramBase { public: - ProgramStore(Context *, - bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA, - bool depthMask, bool ditherEnable, - RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc, - RsDepthFunc depthFunc); - virtual ~ProgramStore(); - virtual void setup(const Context *, ProgramStoreState *); virtual void serialize(OStream *stream) const; virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_STORE; } static ProgramStore *createFromStream(Context *rsc, IStream *stream); + static ObjectBaseRef<ProgramStore> getProgramStore(Context *, + bool colorMaskR, bool colorMaskG, + bool colorMaskB, bool colorMaskA, + bool depthMask, bool ditherEnable, + RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc, + RsDepthFunc depthFunc); void init(); @@ -66,6 +65,15 @@ public: Hal mHal; protected: + virtual void preDestroy() const; + virtual ~ProgramStore(); + +private: + ProgramStore(Context *, + bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA, + bool depthMask, bool ditherEnable, + RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc, + RsDepthFunc depthFunc); }; class ProgramStoreState { @@ -77,6 +85,9 @@ public: ObjectBaseRef<ProgramStore> mDefault; ObjectBaseRef<ProgramStore> mLast; + + // Cache of all existing store programs. + Vector<ProgramStore *> mStorePrograms; }; } diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp index 058a4564e03f..51cb2a8ad490 100644 --- a/libs/rs/rsProgramVertex.cpp +++ b/libs/rs/rsProgramVertex.cpp @@ -150,26 +150,30 @@ ProgramVertexState::~ProgramVertexState() { } void ProgramVertexState::init(Context *rsc) { - const Element *matrixElem = Element::create(rsc, RS_TYPE_MATRIX_4X4, RS_KIND_USER, false, 1); - const Element *f2Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); - const Element *f3Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); - const Element *f4Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); - - rsc->mStateElement.elementBuilderBegin(); - rsc->mStateElement.elementBuilderAdd(matrixElem, "MV", 1); - rsc->mStateElement.elementBuilderAdd(matrixElem, "P", 1); - rsc->mStateElement.elementBuilderAdd(matrixElem, "TexMatrix", 1); - rsc->mStateElement.elementBuilderAdd(matrixElem, "MVP", 1); - const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc); - - rsc->mStateElement.elementBuilderBegin(); - rsc->mStateElement.elementBuilderAdd(f4Elem, "position", 1); - rsc->mStateElement.elementBuilderAdd(f4Elem, "color", 1); - rsc->mStateElement.elementBuilderAdd(f3Elem, "normal", 1); - rsc->mStateElement.elementBuilderAdd(f2Elem, "texture0", 1); - const Element *attrElem = rsc->mStateElement.elementBuilderCreate(rsc); - - Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false); + ObjectBaseRef<const Element> matrixElem = Element::createRef(rsc, RS_TYPE_MATRIX_4X4, + RS_KIND_USER, false, 1); + ObjectBaseRef<const Element> f2Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32, + RS_KIND_USER, false, 2); + ObjectBaseRef<const Element> f3Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32, + RS_KIND_USER, false, 3); + ObjectBaseRef<const Element> f4Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32, + RS_KIND_USER, false, 4); + + Element::Builder constBuilder; + constBuilder.add(matrixElem.get(), "MV", 1); + constBuilder.add(matrixElem.get(), "P", 1); + constBuilder.add(matrixElem.get(), "TexMatrix", 1); + constBuilder.add(matrixElem.get(), "MVP", 1); + ObjectBaseRef<const Element> constInput = constBuilder.create(rsc); + + Element::Builder inputBuilder; + inputBuilder.add(f4Elem.get(), "position", 1); + inputBuilder.add(f4Elem.get(), "color", 1); + inputBuilder.add(f3Elem.get(), "normal", 1); + inputBuilder.add(f2Elem.get(), "texture0", 1); + ObjectBaseRef<const Element> attrElem = inputBuilder.create(rsc); + + ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false); String8 shaderString(RS_SHADER_INTERNAL); shaderString.append("varying vec4 varColor;\n"); @@ -183,13 +187,13 @@ void ProgramVertexState::init(Context *rsc) { uint32_t tmp[4]; tmp[0] = RS_PROGRAM_PARAM_CONSTANT; - tmp[1] = (uint32_t)inputType; + tmp[1] = (uint32_t)inputType.get(); tmp[2] = RS_PROGRAM_PARAM_INPUT; - tmp[3] = (uint32_t)attrElem; + tmp[3] = (uint32_t)attrElem.get(); ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(), shaderString.length(), tmp, 4); - Allocation *alloc = Allocation::createAllocation(rsc, inputType, + Allocation *alloc = Allocation::createAllocation(rsc, inputType.get(), RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS); pv->bindAllocation(rsc, alloc, 0); diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp index 2a05d16e9bbe..5fc64a42cd1f 100644 --- a/libs/rs/rsSampler.cpp +++ b/libs/rs/rsSampler.cpp @@ -48,6 +48,15 @@ Sampler::~Sampler() { mRSC->mHal.funcs.sampler.destroy(mRSC, this); } +void Sampler::preDestroy() const { + for (uint32_t ct = 0; ct < mRSC->mStateSampler.mAllSamplers.size(); ct++) { + if (mRSC->mStateSampler.mAllSamplers[ct] == this) { + mRSC->mStateSampler.mAllSamplers.removeAt(ct); + break; + } + } +} + void Sampler::bindToContext(SamplerState *ss, uint32_t slot) { ss->mSamplers[slot].set(this); mBoundSlot = slot; @@ -66,6 +75,39 @@ Sampler *Sampler::createFromStream(Context *rsc, IStream *stream) { return NULL; } +ObjectBaseRef<Sampler> Sampler::getSampler(Context *rsc, + RsSamplerValue magFilter, + RsSamplerValue minFilter, + RsSamplerValue wrapS, + RsSamplerValue wrapT, + RsSamplerValue wrapR, + float aniso) { + ObjectBaseRef<Sampler> returnRef; + ObjectBase::asyncLock(); + for (uint32_t ct = 0; ct < rsc->mStateSampler.mAllSamplers.size(); ct++) { + Sampler *existing = rsc->mStateSampler.mAllSamplers[ct]; + if (existing->mHal.state.magFilter != magFilter) continue; + if (existing->mHal.state.minFilter != minFilter ) continue; + if (existing->mHal.state.wrapS != wrapS) continue; + if (existing->mHal.state.wrapT != wrapT) continue; + if (existing->mHal.state.wrapR != wrapR) continue; + if (existing->mHal.state.aniso != aniso) continue; + returnRef.set(existing); + ObjectBase::asyncUnlock(); + return returnRef; + } + ObjectBase::asyncUnlock(); + + Sampler *s = new Sampler(rsc, magFilter, minFilter, wrapS, wrapT, wrapR, aniso); + returnRef.set(s); + + ObjectBase::asyncLock(); + rsc->mStateSampler.mAllSamplers.push(s); + ObjectBase::asyncUnlock(); + + return returnRef; +} + //////////////////////////////// namespace android { @@ -78,9 +120,10 @@ RsSampler rsi_SamplerCreate(Context * rsc, RsSamplerValue wrapT, RsSamplerValue wrapR, float aniso) { - Sampler * s = new Sampler(rsc, magFilter, minFilter, wrapS, wrapT, wrapR, aniso); + ObjectBaseRef<Sampler> s = Sampler::getSampler(rsc, magFilter, minFilter, + wrapS, wrapT, wrapR, aniso); s->incUserRef(); - return s; + return s.get(); } }} diff --git a/libs/rs/rsSampler.h b/libs/rs/rsSampler.h index 90b6082c139d..e698132d0f70 100644 --- a/libs/rs/rsSampler.h +++ b/libs/rs/rsSampler.h @@ -30,16 +30,13 @@ class SamplerState; class Sampler : public ObjectBase { public: - Sampler(Context *, - RsSamplerValue magFilter, - RsSamplerValue minFilter, - RsSamplerValue wrapS, - RsSamplerValue wrapT, - RsSamplerValue wrapR, - float aniso = 1.0f); - - virtual ~Sampler(); - + static ObjectBaseRef<Sampler> getSampler(Context *, + RsSamplerValue magFilter, + RsSamplerValue minFilter, + RsSamplerValue wrapS, + RsSamplerValue wrapT, + RsSamplerValue wrapR, + float aniso = 1.0f); void bindToContext(SamplerState *, uint32_t slot); void unbindFromContext(SamplerState *); @@ -65,14 +62,33 @@ public: protected: int32_t mBoundSlot; + virtual void preDestroy() const; + virtual ~Sampler(); + private: Sampler(Context *); + Sampler(Context *, + RsSamplerValue magFilter, + RsSamplerValue minFilter, + RsSamplerValue wrapS, + RsSamplerValue wrapT, + RsSamplerValue wrapR, + float aniso = 1.0f); }; class SamplerState { public: ObjectBaseRef<Sampler> mSamplers[RS_MAX_SAMPLER_SLOT]; + void init(Context *rsc) { + } + void deinit(Context *rsc) { + for (uint32_t i = 0; i < RS_MAX_SAMPLER_SLOT; i ++) { + mSamplers[i].clear(); + } + } + // Cache of all existing raster programs. + Vector<Sampler *> mAllSamplers; }; } diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index e8b1014f53dd..dccf71f046c8 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -19,6 +19,10 @@ #include "utils/Timers.h" #include "utils/StopWatch.h" +#ifndef ANDROID_RS_SERIALIZE +#include <bcinfo/BitcodeTranslator.h> +#endif + using namespace android; using namespace android::renderscript; @@ -28,9 +32,18 @@ using namespace android::renderscript; ScriptC * sc = (ScriptC *) tls->mScript ScriptC::ScriptC(Context *rsc) : Script(rsc) { +#ifndef ANDROID_RS_SERIALIZE + BT = NULL; +#endif } ScriptC::~ScriptC() { +#ifndef ANDROID_RS_SERIALIZE + if (BT) { + delete BT; + BT = NULL; + } +#endif mRSC->mHal.funcs.script.destroy(mRSC, this); } @@ -181,6 +194,22 @@ bool ScriptC::runCompiler(Context *rsc, size_t bitcodeLen) { //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen); +#ifndef ANDROID_RS_SERIALIZE + uint32_t sdkVersion = rsc->getTargetSdkVersion(); + if (BT) { + delete BT; + } + BT = new bcinfo::BitcodeTranslator((const char *)bitcode, bitcodeLen, + sdkVersion); + if (!BT->translate()) { + LOGE("Failed to translate bitcode from version: %u", sdkVersion); + delete BT; + BT = NULL; + return false; + } + bitcode = (const uint8_t *) BT->getTranslatedBitcode(); + bitcodeLen = BT->getTranslatedBitcodeSize(); +#endif rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0); diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h index 5c191d93cf46..c65a5bf7a06b 100644 --- a/libs/rs/rsScriptC.h +++ b/libs/rs/rsScriptC.h @@ -21,6 +21,9 @@ #include "RenderScriptEnv.h" +#ifndef ANDROID_RS_SERIALIZE +#include "bcinfo/BitcodeTranslator.h" +#endif // --------------------------------------------------------------------------- namespace android { @@ -61,6 +64,10 @@ public: void setupScript(Context *); void setupGLState(Context *); Script * setTLS(Script *); + private: +#ifndef ANDROID_RS_SERIALIZE + bcinfo::BitcodeTranslator *BT; +#endif }; class ScriptCState { diff --git a/libs/rs/rsSignal.cpp b/libs/rs/rsSignal.cpp index ccd20b95c100..413ac2bb201e 100644 --- a/libs/rs/rsSignal.cpp +++ b/libs/rs/rsSignal.cpp @@ -68,26 +68,43 @@ void Signal::set() { } } -void Signal::wait() { +bool Signal::wait(uint64_t timeout) { int status; + bool ret = false; status = pthread_mutex_lock(&mMutex); if (status) { LOGE("LocklessCommandFifo: error %i locking for condition.", status); - return; + return false; } if (!mSet) { - status = pthread_cond_wait(&mCondition, &mMutex); - if (status) { - LOGE("LocklessCommandFifo: error %i waiting on condition.", status); + if (!timeout) { + status = pthread_cond_wait(&mCondition, &mMutex); + } else { +#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE) + status = pthread_cond_timeout_np(&mCondition, &mMutex, timeout / 1000000); +#else + // This is safe it will just make things less reponsive + status = pthread_cond_wait(&mCondition, &mMutex); +#endif + } + } + + if (!status) { + mSet = false; + ret = true; + } else { + if (status != ETIMEDOUT) { + LOGE("LocklessCommandFifo: error %i waiting for condition.", status); } } - mSet = false; status = pthread_mutex_unlock(&mMutex); if (status) { LOGE("LocklessCommandFifo: error %i unlocking for condition.", status); } + + return ret; } diff --git a/libs/rs/rsSignal.h b/libs/rs/rsSignal.h index 2e760f158e53..fc3188301334 100644 --- a/libs/rs/rsSignal.h +++ b/libs/rs/rsSignal.h @@ -31,7 +31,10 @@ public: bool init(); void set(); - void wait(); + + // returns true if the signal occured + // false for timeout + bool wait(uint64_t timeout = 0); protected: bool mSet; diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp index 1c8b89c25d55..fe2c52ea4662 100644 --- a/libs/rs/rsThreadIO.cpp +++ b/libs/rs/rsThreadIO.cpp @@ -113,8 +113,10 @@ void ThreadIO::coreGetReturn(void *data, size_t dataLen) { } -bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) { +bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait) { bool ret = false; + uint64_t startTime = con->getTime(); + while (!mToCore.isEmpty() || waitForCommand) { uint32_t cmdID = 0; uint32_t cmdSize = 0; @@ -122,9 +124,17 @@ bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) { if (con->props.mLogTimes) { con->timerSet(Context::RS_TIMER_IDLE); } - const void * data = mToCore.get(&cmdID, &cmdSize); + + uint64_t delay = 0; + if (waitForCommand) { + delay = timeToWait - (con->getTime() - startTime); + if (delay > timeToWait) { + delay = 0; + } + } + const void * data = mToCore.get(&cmdID, &cmdSize, delay); if (!cmdSize) { - // exception occured, probably shutdown. + // exception or timeout occurred. return false; } if (con->props.mLogTimes) { diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h index cad731864942..9036118a0fa0 100644 --- a/libs/rs/rsThreadIO.h +++ b/libs/rs/rsThreadIO.h @@ -37,7 +37,7 @@ public: // Plays back commands from the client. // Returns true if any commands were processed. - bool playCoreCommands(Context *con, bool waitForCommand); + bool playCoreCommands(Context *con, bool waitForCommand, uint64_t timeToWait); //LocklessCommandFifo mToCore; diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp index 10e3182c6389..9a6a31b4f89f 100644 --- a/libs/rs/rsType.cpp +++ b/libs/rs/rsType.cpp @@ -25,7 +25,7 @@ Type::Type(Context *rsc) : ObjectBase(rsc) { clear(); } -void Type::preDestroy() { +void Type::preDestroy() const { for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) { if (mRSC->mStateType.mTypes[ct] == this) { mRSC->mStateType.mTypes.removeAt(ct); @@ -58,6 +58,7 @@ TypeState::TypeState() { } TypeState::~TypeState() { + rsAssert(!mTypes.size()); } size_t Type::getOffsetForFace(uint32_t face) const { @@ -183,7 +184,9 @@ Type *Type::createFromStream(Context *rsc, IStream *stream) { uint32_t z = stream->loadU32(); uint8_t lod = stream->loadU8(); uint8_t faces = stream->loadU8(); - return Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 ); + Type *type = Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 ); + elem->decUserRef(); + return type; } bool Type::getIsNp2() const { @@ -203,24 +206,11 @@ bool Type::getIsNp2() const { return false; } -bool Type::isEqual(const Type *other) const { - if (other == NULL) { - return false; - } - if (other->getElement()->isEqual(getElement()) && - other->getDimX() == mDimX && - other->getDimY() == mDimY && - other->getDimZ() == mDimZ && - other->getDimLOD() == mDimLOD && - other->getDimFaces() == mFaces) { - return true; - } - return false; -} +ObjectBaseRef<Type> Type::getTypeRef(Context *rsc, const Element *e, + uint32_t dimX, uint32_t dimY, uint32_t dimZ, + bool dimLOD, bool dimFaces) { + ObjectBaseRef<Type> returnRef; -Type * Type::getType(Context *rsc, const Element *e, - uint32_t dimX, uint32_t dimY, uint32_t dimZ, - bool dimLOD, bool dimFaces) { TypeState * stc = &rsc->mStateType; ObjectBase::asyncLock(); @@ -232,14 +222,15 @@ Type * Type::getType(Context *rsc, const Element *e, if (t->getDimZ() != dimZ) continue; if (t->getDimLOD() != dimLOD) continue; if (t->getDimFaces() != dimFaces) continue; - t->incUserRef(); + returnRef.set(t); ObjectBase::asyncUnlock(); - return t; + return returnRef; } ObjectBase::asyncUnlock(); Type *nt = new Type(rsc); + returnRef.set(nt); nt->mElement.set(e); nt->mDimX = dimX; nt->mDimY = dimY; @@ -247,25 +238,24 @@ Type * Type::getType(Context *rsc, const Element *e, nt->mDimLOD = dimLOD; nt->mFaces = dimFaces; nt->compute(); - nt->incUserRef(); ObjectBase::asyncLock(); stc->mTypes.push(nt); ObjectBase::asyncUnlock(); - return nt; + return returnRef; } -Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const { - return getType(rsc, mElement.get(), dimX, - mDimY, mDimZ, mDimLOD, mFaces); +ObjectBaseRef<Type> Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const { + return getTypeRef(rsc, mElement.get(), dimX, + mDimY, mDimZ, mDimLOD, mFaces); } -Type * Type::cloneAndResize2D(Context *rsc, +ObjectBaseRef<Type> Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const { - return getType(rsc, mElement.get(), dimX, dimY, - mDimZ, mDimLOD, mFaces); + return getTypeRef(rsc, mElement.get(), dimX, dimY, + mDimZ, mDimLOD, mFaces); } diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h index 086db337093b..bc0d9ffdbe46 100644 --- a/libs/rs/rsType.h +++ b/libs/rs/rsType.h @@ -62,14 +62,20 @@ public: virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_TYPE; } static Type *createFromStream(Context *rsc, IStream *stream); - bool isEqual(const Type *other) const; + ObjectBaseRef<Type> cloneAndResize1D(Context *rsc, uint32_t dimX) const; + ObjectBaseRef<Type> cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const; - Type * cloneAndResize1D(Context *rsc, uint32_t dimX) const; - Type * cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const; + static ObjectBaseRef<Type> getTypeRef(Context *rsc, const Element *e, + uint32_t dimX, uint32_t dimY, uint32_t dimZ, + bool dimLOD, bool dimFaces); - static Type * getType(Context *rsc, const Element *e, - uint32_t dimX, uint32_t dimY, uint32_t dimZ, - bool dimLOD, bool dimFaces); + static Type* getType(Context *rsc, const Element *e, + uint32_t dimX, uint32_t dimY, uint32_t dimZ, + bool dimLOD, bool dimFaces) { + ObjectBaseRef<Type> type = getTypeRef(rsc, e, dimX, dimY, dimZ, dimLOD, dimFaces); + type->incUserRef(); + return type.get(); + } protected: struct LOD { @@ -105,7 +111,7 @@ protected: uint32_t mLODCount; protected: - virtual void preDestroy(); + virtual void preDestroy() const; virtual ~Type(); private: diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h index 6a4537b392a2..21dff218c868 100644 --- a/libs/rs/rs_hal.h +++ b/libs/rs/rs_hal.h @@ -40,6 +40,19 @@ class FBOCache; typedef void *(*RsHalSymbolLookupFunc)(void *usrptr, char const *symbolName); +typedef struct { + const void *in; + void *out; + const void *usr; + size_t usr_len; + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t lod; + RsAllocationCubemapFace face; + uint32_t ar[16]; +} RsForEachStubParamStruct; + /** * Script management functions */ diff --git a/libs/rs/scriptc/rs_allocation.rsh b/libs/rs/scriptc/rs_allocation.rsh new file mode 100644 index 000000000000..1e755cd38ceb --- /dev/null +++ b/libs/rs/scriptc/rs_allocation.rsh @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file rs_allocation.rsh + * \brief Allocation routines + * + * + */ + +#ifndef __RS_ALLOCATION_RSH__ +#define __RS_ALLOCATION_RSH__ + +/** + * Returns the Allocation for a given pointer. The pointer should point within + * a valid allocation. The results are undefined if the pointer is not from a + * valid allocation. + */ +extern rs_allocation __attribute__((overloadable)) + rsGetAllocation(const void *); + +/** + * Query the dimension of an allocation. + * + * @return uint32_t The X dimension of the allocation. + */ +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimX(rs_allocation); + +/** + * Query the dimension of an allocation. + * + * @return uint32_t The Y dimension of the allocation. + */ +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimY(rs_allocation); + +/** + * Query the dimension of an allocation. + * + * @return uint32_t The Z dimension of the allocation. + */ +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimZ(rs_allocation); + +/** + * Query an allocation for the presence of more than one LOD. + * + * @return uint32_t Returns 1 if more than one LOD is present, 0 otherwise. + */ +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimLOD(rs_allocation); + +/** + * Query an allocation for the presence of more than one face. + * + * @return uint32_t Returns 1 if more than one face is present, 0 otherwise. + */ +extern uint32_t __attribute__((overloadable)) + rsAllocationGetDimFaces(rs_allocation); + +/** + * Copy part of an allocation from another allocation. + * + * @param dstAlloc Allocation to copy data into. + * @param dstOff The offset of the first element to be copied in + * the destination allocation. + * @param dstMip Mip level in the destination allocation. + * @param count The number of elements to be copied. + * @param srcAlloc The source data allocation. + * @param srcOff The offset of the first element in data to be + * copied in the source allocation. + * @param srcMip Mip level in the source allocation. + */ +extern void __attribute__((overloadable)) + rsAllocationCopy1DRange(rs_allocation dstAlloc, + uint32_t dstOff, uint32_t dstMip, + uint32_t count, + rs_allocation srcAlloc, + uint32_t srcOff, uint32_t srcMip); + +/** + * Copy a rectangular region into the allocation from another + * allocation. + * + * @param dstAlloc allocation to copy data into. + * @param dstXoff X offset of the region to update in the + * destination allocation. + * @param dstYoff Y offset of the region to update in the + * destination allocation. + * @param dstMip Mip level in the destination allocation. + * @param dstFace Cubemap face of the destination allocation, + * ignored for allocations that aren't cubemaps. + * @param width Width of the incoming region to update. + * @param height Height of the incoming region to update. + * @param srcAlloc The source data allocation. + * @param srcXoff X offset in data of the source allocation. + * @param srcYoff Y offset in data of the source allocation. + * @param srcMip Mip level in the source allocation. + * @param srcFace Cubemap face of the source allocation, + * ignored for allocations that aren't cubemaps. + */ +extern void __attribute__((overloadable)) + rsAllocationCopy2DRange(rs_allocation dstAlloc, + uint32_t dstXoff, uint32_t dstYoff, + uint32_t dstMip, + rs_allocation_cubemap_face dstFace, + uint32_t width, uint32_t height, + rs_allocation srcAlloc, + uint32_t srcXoff, uint32_t srcYoff, + uint32_t srcMip, + rs_allocation_cubemap_face srcFace); + + +/** + * Extract a single element from an allocation. + */ +extern const void * __attribute__((overloadable)) + rsGetElementAt(rs_allocation, uint32_t x); +/** + * \overload + */ +extern const void * __attribute__((overloadable)) + rsGetElementAt(rs_allocation, uint32_t x, uint32_t y); +/** + * \overload + */ +extern const void * __attribute__((overloadable)) + rsGetElementAt(rs_allocation, uint32_t x, uint32_t y, uint32_t z); + +#endif + diff --git a/libs/rs/scriptc/rs_atomic.rsh b/libs/rs/scriptc/rs_atomic.rsh new file mode 100644 index 000000000000..95513ad623f1 --- /dev/null +++ b/libs/rs/scriptc/rs_atomic.rsh @@ -0,0 +1,248 @@ +/* + * 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. + */ + +/** @file rs_atomic.rsh + * \brief Atomic routines + * + * + */ + +#ifndef __RS_ATOMIC_RSH__ +#define __RS_ATOMIC_RSH__ + + +/** + * Atomic add one to the value at addr. + * Equal to rsAtomicAdd(addr, 1) + * + * @param addr Address of value to increment + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicInc(volatile int32_t* addr); +/** + * Atomic add one to the value at addr. + * Equal to rsAtomicAdd(addr, 1) + * + * @param addr Address of value to increment + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicInc(volatile uint32_t* addr); + +/** + * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1) + * + * @param addr Address of value to decrement + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicDec(volatile int32_t* addr); +/** + * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1) + * + * @param addr Address of value to decrement + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicDec(volatile uint32_t* addr); + +/** + * Atomic add a value to the value at addr. addr[0] += value + * + * @param addr Address of value to modify + * @param value Amount to add to the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicAdd(volatile int32_t* addr, int32_t value); +/** + * Atomic add a value to the value at addr. addr[0] += value + * + * @param addr Address of value to modify + * @param value Amount to add to the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicAdd(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Subtract a value from the value at addr. addr[0] -= value + * + * @param addr Address of value to modify + * @param value Amount to subtract from the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicSub(volatile int32_t* addr, int32_t value); +/** + * Atomic Subtract a value from the value at addr. addr[0] -= value + * + * @param addr Address of value to modify + * @param value Amount to subtract from the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicSub(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Bitwise and a value from the value at addr. addr[0] &= value + * + * @param addr Address of value to modify + * @param value Amount to and with the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicAnd(volatile int32_t* addr, int32_t value); +/** + * Atomic Bitwise and a value from the value at addr. addr[0] &= value + * + * @param addr Address of value to modify + * @param value Amount to and with the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicAnd(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Bitwise or a value from the value at addr. addr[0] |= value + * + * @param addr Address of value to modify + * @param value Amount to or with the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicOr(volatile int32_t* addr, int32_t value); +/** + * Atomic Bitwise or a value from the value at addr. addr[0] |= value + * + * @param addr Address of value to modify + * @param value Amount to or with the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicOr(volatile uint32_t* addr, uint32_t value); + +/** + * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value + * + * @param addr Address of value to modify + * @param value Amount to xor with the value at addr + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicXor(volatile uint32_t* addr, uint32_t value); +/** + * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value + * + * @param addr Address of value to modify + * @param value Amount to xor with the value at addr + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicXor(volatile int32_t* addr, int32_t value); + +/** + * Atomic Set the value at addr to the min of addr and value + * addr[0] = rsMin(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicMin(volatile uint32_t* addr, uint32_t value); +/** + * Atomic Set the value at addr to the min of addr and value + * addr[0] = rsMin(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicMin(volatile int32_t* addr, int32_t value); + +/** + * Atomic Set the value at addr to the max of addr and value + * addr[0] = rsMax(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicMax(volatile uint32_t* addr, uint32_t value); +/** + * Atomic Set the value at addr to the max of addr and value + * addr[0] = rsMin(addr[0], value) + * + * @param addr Address of value to modify + * @param value comparison value + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicMax(volatile int32_t* addr, int32_t value); + +/** + * Compare-and-set operation with a full memory barrier. + * + * If the value at addr matches compareValue then newValue is written. + * + * @param addr The address to compare and replace if the compare passes. + * @param compareValue The value to test addr[0] against. + * @param newValue The value to write if the test passes. + * + * @return old value + */ +extern int32_t __attribute__((overloadable)) + rsAtomicCas(volatile int32_t* addr, int32_t compareValue, int32_t newValue); + +/** + * Compare-and-set operation with a full memory barrier. + * + * If the value at addr matches compareValue then newValue is written. + * + * @param addr The address to compare and replace if the compare passes. + * @param compareValue The value to test addr[0] against. + * @param newValue The value to write if the test passes. + * + * @return old value + */ +extern uint32_t __attribute__((overloadable)) + rsAtomicCas(volatile uint32_t* addr, int32_t compareValue, int32_t newValue); + + +#endif + diff --git a/libs/rs/scriptc/rs_cl.rsh b/libs/rs/scriptc/rs_cl.rsh index d78e62e1d54a..e402b86864c9 100644 --- a/libs/rs/scriptc/rs_cl.rsh +++ b/libs/rs/scriptc/rs_cl.rsh @@ -1,8 +1,28 @@ +/* + * 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. + */ + +/** @file rs_cl.rsh + * \brief Additional compute routines + * + * + */ + #ifndef __RS_CL_RSH__ #define __RS_CL_RSH__ -#define _RS_RUNTIME extern - // Conversions #define CVT_FUNC_2(typeout, typein) \ _RS_RUNTIME typeout##2 __attribute__((overloadable)) \ @@ -444,6 +464,5 @@ _RS_RUNTIME float4 __attribute__((overloadable)) normalize(float4 v); #undef IN_FUNC_IN #undef XN_FUNC_XN_XN_BODY #undef IN_FUNC_IN_IN_BODY -#undef _RS_RUNTIME #endif diff --git a/libs/rs/scriptc/rs_core.rsh b/libs/rs/scriptc/rs_core.rsh index d939fb33d6ea..be900cb71f9c 100644 --- a/libs/rs/scriptc/rs_core.rsh +++ b/libs/rs/scriptc/rs_core.rsh @@ -1,579 +1,166 @@ +/* + * 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. + */ + +/** @file rs_core.rsh + * \brief todo-jsams + * + * todo-jsams + * + */ + #ifndef __RS_CORE_RSH__ #define __RS_CORE_RSH__ #define _RS_RUNTIME extern +#include "rs_types.rsh" +#include "rs_allocation.rsh" +#include "rs_atomic.rsh" +#include "rs_cl.rsh" +#include "rs_debug.rsh" +#include "rs_math.rsh" +#include "rs_matrix.rsh" +#include "rs_object.rsh" +#include "rs_quaternion.rsh" +#include "rs_time.rsh" + + + /** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, float); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, float, float); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, float, float, float); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, float, float, float, float); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, double); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, const rs_matrix4x4 *); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, const rs_matrix3x3 *); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, const rs_matrix2x2 *); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, int); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, uint); -/** - * Debug function. Prints a string and value to the log. - */ -extern void __attribute__((overloadable)) - rsDebug(const char *, long); -/** - * Debug function. Prints a string and value to the log. + * Send a message back to the client. Will not block and returns true + * if the message was sendable and false if the fifo was full. + * A message ID is required. Data payload is optional. */ -extern void __attribute__((overloadable)) - rsDebug(const char *, unsigned long); +extern bool __attribute__((overloadable)) + rsSendToClient(int cmdID); /** - * Debug function. Prints a string and value to the log. + * \overload */ -extern void __attribute__((overloadable)) - rsDebug(const char *, long long); +extern bool __attribute__((overloadable)) + rsSendToClient(int cmdID, const void *data, uint len); /** - * Debug function. Prints a string and value to the log. + * Send a message back to the client, blocking until the message is queued. + * A message ID is required. Data payload is optional. */ extern void __attribute__((overloadable)) - rsDebug(const char *, unsigned long long); + rsSendToClientBlocking(int cmdID); /** - * Debug function. Prints a string and value to the log. + * \overload */ extern void __attribute__((overloadable)) - rsDebug(const char *, const void *); -#define RS_DEBUG(a) rsDebug(#a, a) -#define RS_DEBUG_MARKER rsDebug(__FILE__, __LINE__) + rsSendToClientBlocking(int cmdID, const void *data, uint len); /** - * Debug function. Prints a string and value to the log. - */ -_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float2 v); -/** - * Debug function. Prints a string and value to the log. - */ -_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float3 v); -/** - * Debug function. Prints a string and value to the log. - */ -_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float4 v); - - -/** - * Pack floating point (0-1) RGB values into a uchar4. The alpha component is - * set to 255 (1.0). - * - * @param r - * @param g - * @param b + * Launch order hint for rsForEach calls. This provides a hint to the system to + * determine in which order the root function of the target is called with each + * cell of the allocation. * - * @return uchar4 + * This is a hint and implementations may not obey the order. */ -_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b); +enum rs_for_each_strategy { + RS_FOR_EACH_STRATEGY_SERIAL, + RS_FOR_EACH_STRATEGY_DONT_CARE, + RS_FOR_EACH_STRATEGY_DST_LINEAR, + RS_FOR_EACH_STRATEGY_TILE_SMALL, + RS_FOR_EACH_STRATEGY_TILE_MEDIUM, + RS_FOR_EACH_STRATEGY_TILE_LARGE +}; -/** - * Pack floating point (0-1) RGBA values into a uchar4. - * - * @param r - * @param g - * @param b - * @param a - * - * @return uchar4 - */ -_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b, float a); /** - * Pack floating point (0-1) RGB values into a uchar4. The alpha component is - * set to 255 (1.0). - * - * @param color - * - * @return uchar4 + * Structure to provide extra information to a rsForEach call. Primarly used to + * restrict the call to a subset of cells in the allocation. */ -_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float3 color); +typedef struct rs_script_call { + enum rs_for_each_strategy strategy; + uint32_t xStart; + uint32_t xEnd; + uint32_t yStart; + uint32_t yEnd; + uint32_t zStart; + uint32_t zEnd; + uint32_t arrayStart; + uint32_t arrayEnd; +} rs_script_call_t; /** - * Pack floating point (0-1) RGBA values into a uchar4. + * Make a script to script call to launch work. One of the input or output is + * required to be a valid object. The input and output must be of the same + * dimensions. + * API 10-13 * - * @param color + * @param script The target script to call + * @param input The allocation to source data from + * @param output the allocation to write date into + * @param usrData The user definied params to pass to the root script. May be + * NULL. + * @param sc Extra control infomation used to select a sub-region of the + * allocation to be processed or suggest a walking strategy. May be + * NULL. * - * @return uchar4 - */ -_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float4 color); - -/** - * Unpack a uchar4 color to float4. The resulting float range will be (0-1). - * - * @param c - * - * @return float4 - */ -_RS_RUNTIME float4 rsUnpackColor8888(uchar4 c); - - -///////////////////////////////////////////////////// -// Matrix ops -///////////////////////////////////////////////////// - + * */ +#if !defined(RS_VERSION) || (RS_VERSION < 14) +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, + rs_allocation output, const void * usrData, + const rs_script_call_t *sc); /** - * Set one element of a matrix. - * - * @param m The matrix to be set - * @param row - * @param col - * @param v - * - * @return void + * \overload */ -_RS_RUNTIME void __attribute__((overloadable)) -rsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v); -_RS_RUNTIME void __attribute__((overloadable)) -rsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v); -_RS_RUNTIME void __attribute__((overloadable)) -rsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v); +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, + rs_allocation output, const void * usrData); +#else /** - * Get one element of a matrix. - * - * @param m The matrix to read from - * @param row - * @param col + * Make a script to script call to launch work. One of the input or output is + * required to be a valid object. The input and output must be of the same + * dimensions. + * API 14+ * - * @return float - */ -_RS_RUNTIME float __attribute__((overloadable)) -rsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col); -_RS_RUNTIME float __attribute__((overloadable)) -rsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col); -_RS_RUNTIME float __attribute__((overloadable)) -rsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col); - -/** - * Set the elements of a matrix to the identity matrix. + * @param script The target script to call + * @param input The allocation to source data from + * @param output the allocation to write date into + * @param usrData The user definied params to pass to the root script. May be + * NULL. + * @param usrDataLen The size of the userData structure. This will be used to + * perform a shallow copy of the data if necessary. + * @param sc Extra control infomation used to select a sub-region of the + * allocation to be processed or suggest a walking strategy. May be + * NULL. * - * @param m */ -extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix4x4 *m); -extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix3x3 *m); -extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix2x2 *m); - -/** - * Set the elements of a matrix from an array of floats. - * - * @param m - */ -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const float *v); -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix3x3 *m, const float *v); -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix2x2 *m, const float *v); - +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, rs_allocation output, + const void * usrData, size_t usrDataLen, const rs_script_call_t *); /** - * Set the elements of a matrix from another matrix. - * - * @param m + * \overload */ -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix4x4 *v); -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix3x3 *v); -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix2x2 *v); -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix3x3 *m, const rs_matrix3x3 *v); -extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix2x2 *m, const rs_matrix2x2 *v); - +extern void __attribute__((overloadable)) + rsForEach(rs_script script, rs_allocation input, rs_allocation output, + const void * usrData, size_t usrDataLen); /** - * Load a rotation matrix. - * - * @param m - * @param rot - * @param x - * @param y - * @param z + * \overload */ extern void __attribute__((overloadable)) -rsMatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z); - -extern void __attribute__((overloadable)) -rsMatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z); - -extern void __attribute__((overloadable)) -rsMatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z); - -extern void __attribute__((overloadable)) -rsMatrixLoadMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs); - -extern void __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *rhs); - -extern void __attribute__((overloadable)) -rsMatrixLoadMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs); - -extern void __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *rhs); - -extern void __attribute__((overloadable)) -rsMatrixLoadMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs); - -extern void __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *rhs); - -extern void __attribute__((overloadable)) -rsMatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z); - -extern void __attribute__((overloadable)) -rsMatrixScale(rs_matrix4x4 *m, float x, float y, float z); - -extern void __attribute__((overloadable)) -rsMatrixTranslate(rs_matrix4x4 *m, float x, float y, float z); - -extern void __attribute__((overloadable)) -rsMatrixLoadOrtho(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far); - -extern void __attribute__((overloadable)) -rsMatrixLoadFrustum(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far); - -extern void __attribute__((overloadable)) -rsMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far); - -#if !defined(RS_VERSION) || (RS_VERSION < 14) -_RS_RUNTIME float4 __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix4x4 *m, float4 in); - -_RS_RUNTIME float4 __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix4x4 *m, float3 in); - -_RS_RUNTIME float4 __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix4x4 *m, float2 in); - -_RS_RUNTIME float3 __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix3x3 *m, float3 in); - -_RS_RUNTIME float3 __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix3x3 *m, float2 in); - -_RS_RUNTIME float2 __attribute__((overloadable)) -rsMatrixMultiply(rs_matrix2x2 *m, float2 in); -#else -_RS_RUNTIME float4 __attribute__((overloadable)) -rsMatrixMultiply(const rs_matrix4x4 *m, float4 in); - -_RS_RUNTIME float4 __attribute__((overloadable)) -rsMatrixMultiply(const rs_matrix4x4 *m, float3 in); - -_RS_RUNTIME float4 __attribute__((overloadable)) -rsMatrixMultiply(const rs_matrix4x4 *m, float2 in); - -_RS_RUNTIME float3 __attribute__((overloadable)) -rsMatrixMultiply(const rs_matrix3x3 *m, float3 in); - -_RS_RUNTIME float3 __attribute__((overloadable)) -rsMatrixMultiply(const rs_matrix3x3 *m, float2 in); - -_RS_RUNTIME float2 __attribute__((overloadable)) -rsMatrixMultiply(const rs_matrix2x2 *m, float2 in); + rsForEach(rs_script script, rs_allocation input, rs_allocation output); #endif -// Returns true if the matrix was successfully inversed -extern bool __attribute__((overloadable)) rsMatrixInverse(rs_matrix4x4 *m); -extern bool __attribute__((overloadable)) rsMatrixInverseTranspose(rs_matrix4x4 *m); -extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix4x4 *m); -extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix3x3 *m); -extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix2x2 *m); - -///////////////////////////////////////////////////// -// quaternion ops -///////////////////////////////////////////////////// - -static void __attribute__((overloadable)) -rsQuaternionSet(rs_quaternion *q, float w, float x, float y, float z) { - q->w = w; - q->x = x; - q->y = y; - q->z = z; -} - -static void __attribute__((overloadable)) -rsQuaternionSet(rs_quaternion *q, const rs_quaternion *rhs) { - q->w = rhs->w; - q->x = rhs->x; - q->y = rhs->y; - q->z = rhs->z; -} - -static void __attribute__((overloadable)) -rsQuaternionMultiply(rs_quaternion *q, float s) { - q->w *= s; - q->x *= s; - q->y *= s; - q->z *= s; -} - -static void __attribute__((overloadable)) -rsQuaternionMultiply(rs_quaternion *q, const rs_quaternion *rhs) { - q->w = -q->x*rhs->x - q->y*rhs->y - q->z*rhs->z + q->w*rhs->w; - q->x = q->x*rhs->w + q->y*rhs->z - q->z*rhs->y + q->w*rhs->x; - q->y = -q->x*rhs->z + q->y*rhs->w + q->z*rhs->x + q->w*rhs->y; - q->z = q->x*rhs->y - q->y*rhs->x + q->z*rhs->w + q->w*rhs->z; -} - -static void -rsQuaternionAdd(rs_quaternion *q, const rs_quaternion *rhs) { - q->w *= rhs->w; - q->x *= rhs->x; - q->y *= rhs->y; - q->z *= rhs->z; -} - -static void -rsQuaternionLoadRotateUnit(rs_quaternion *q, float rot, float x, float y, float z) { - rot *= (float)(M_PI / 180.0f) * 0.5f; - float c = cos(rot); - float s = sin(rot); - - q->w = c; - q->x = x * s; - q->y = y * s; - q->z = z * s; -} - -static void -rsQuaternionLoadRotate(rs_quaternion *q, float rot, float x, float y, float z) { - const float len = x*x + y*y + z*z; - if (len != 1) { - const float recipLen = 1.f / sqrt(len); - x *= recipLen; - y *= recipLen; - z *= recipLen; - } - rsQuaternionLoadRotateUnit(q, rot, x, y, z); -} - -static void -rsQuaternionConjugate(rs_quaternion *q) { - q->x = -q->x; - q->y = -q->y; - q->z = -q->z; -} - -static float -rsQuaternionDot(const rs_quaternion *q0, const rs_quaternion *q1) { - return q0->w*q1->w + q0->x*q1->x + q0->y*q1->y + q0->z*q1->z; -} - -static void -rsQuaternionNormalize(rs_quaternion *q) { - const float len = rsQuaternionDot(q, q); - if (len != 1) { - const float recipLen = 1.f / sqrt(len); - rsQuaternionMultiply(q, recipLen); - } -} - -static void -rsQuaternionSlerp(rs_quaternion *q, const rs_quaternion *q0, const rs_quaternion *q1, float t) { - if (t <= 0.0f) { - rsQuaternionSet(q, q0); - return; - } - if (t >= 1.0f) { - rsQuaternionSet(q, q1); - return; - } - - rs_quaternion tempq0, tempq1; - rsQuaternionSet(&tempq0, q0); - rsQuaternionSet(&tempq1, q1); - - float angle = rsQuaternionDot(q0, q1); - if (angle < 0) { - rsQuaternionMultiply(&tempq0, -1.0f); - angle *= -1.0f; - } - - float scale, invScale; - if (angle + 1.0f > 0.05f) { - if (1.0f - angle >= 0.05f) { - float theta = acos(angle); - float invSinTheta = 1.0f / sin(theta); - scale = sin(theta * (1.0f - t)) * invSinTheta; - invScale = sin(theta * t) * invSinTheta; - } else { - scale = 1.0f - t; - invScale = t; - } - } else { - rsQuaternionSet(&tempq1, tempq0.z, -tempq0.y, tempq0.x, -tempq0.w); - scale = sin(M_PI * (0.5f - t)); - invScale = sin(M_PI * t); - } - - rsQuaternionSet(q, tempq0.w*scale + tempq1.w*invScale, tempq0.x*scale + tempq1.x*invScale, - tempq0.y*scale + tempq1.y*invScale, tempq0.z*scale + tempq1.z*invScale); -} - -static void rsQuaternionGetMatrixUnit(rs_matrix4x4 *m, const rs_quaternion *q) { - float x2 = 2.0f * q->x * q->x; - float y2 = 2.0f * q->y * q->y; - float z2 = 2.0f * q->z * q->z; - float xy = 2.0f * q->x * q->y; - float wz = 2.0f * q->w * q->z; - float xz = 2.0f * q->x * q->z; - float wy = 2.0f * q->w * q->y; - float wx = 2.0f * q->w * q->x; - float yz = 2.0f * q->y * q->z; - - m->m[0] = 1.0f - y2 - z2; - m->m[1] = xy - wz; - m->m[2] = xz + wy; - m->m[3] = 0.0f; - - m->m[4] = xy + wz; - m->m[5] = 1.0f - x2 - z2; - m->m[6] = yz - wx; - m->m[7] = 0.0f; - - m->m[8] = xz - wy; - m->m[9] = yz - wx; - m->m[10] = 1.0f - x2 - y2; - m->m[11] = 0.0f; - - m->m[12] = 0.0f; - m->m[13] = 0.0f; - m->m[14] = 0.0f; - m->m[15] = 1.0f; -} - -///////////////////////////////////////////////////// -// utility funcs -///////////////////////////////////////////////////// -__inline__ static void __attribute__((overloadable, always_inline)) -rsExtractFrustumPlanes(const rs_matrix4x4 *modelViewProj, - float4 *left, float4 *right, - float4 *top, float4 *bottom, - float4 *near, float4 *far) { - // x y z w = a b c d in the plane equation - left->x = modelViewProj->m[3] + modelViewProj->m[0]; - left->y = modelViewProj->m[7] + modelViewProj->m[4]; - left->z = modelViewProj->m[11] + modelViewProj->m[8]; - left->w = modelViewProj->m[15] + modelViewProj->m[12]; - - right->x = modelViewProj->m[3] - modelViewProj->m[0]; - right->y = modelViewProj->m[7] - modelViewProj->m[4]; - right->z = modelViewProj->m[11] - modelViewProj->m[8]; - right->w = modelViewProj->m[15] - modelViewProj->m[12]; - - top->x = modelViewProj->m[3] - modelViewProj->m[1]; - top->y = modelViewProj->m[7] - modelViewProj->m[5]; - top->z = modelViewProj->m[11] - modelViewProj->m[9]; - top->w = modelViewProj->m[15] - modelViewProj->m[13]; - - bottom->x = modelViewProj->m[3] + modelViewProj->m[1]; - bottom->y = modelViewProj->m[7] + modelViewProj->m[5]; - bottom->z = modelViewProj->m[11] + modelViewProj->m[9]; - bottom->w = modelViewProj->m[15] + modelViewProj->m[13]; - - near->x = modelViewProj->m[3] + modelViewProj->m[2]; - near->y = modelViewProj->m[7] + modelViewProj->m[6]; - near->z = modelViewProj->m[11] + modelViewProj->m[10]; - near->w = modelViewProj->m[15] + modelViewProj->m[14]; - - far->x = modelViewProj->m[3] - modelViewProj->m[2]; - far->y = modelViewProj->m[7] - modelViewProj->m[6]; - far->z = modelViewProj->m[11] - modelViewProj->m[10]; - far->w = modelViewProj->m[15] - modelViewProj->m[14]; - - float len = length(left->xyz); - *left /= len; - len = length(right->xyz); - *right /= len; - len = length(top->xyz); - *top /= len; - len = length(bottom->xyz); - *bottom /= len; - len = length(near->xyz); - *near /= len; - len = length(far->xyz); - *far /= len; -} - -__inline__ static bool __attribute__((overloadable, always_inline)) -rsIsSphereInFrustum(float4 *sphere, - float4 *left, float4 *right, - float4 *top, float4 *bottom, - float4 *near, float4 *far) { - - float distToCenter = dot(left->xyz, sphere->xyz) + left->w; - if (distToCenter < -sphere->w) { - return false; - } - distToCenter = dot(right->xyz, sphere->xyz) + right->w; - if (distToCenter < -sphere->w) { - return false; - } - distToCenter = dot(top->xyz, sphere->xyz) + top->w; - if (distToCenter < -sphere->w) { - return false; - } - distToCenter = dot(bottom->xyz, sphere->xyz) + bottom->w; - if (distToCenter < -sphere->w) { - return false; - } - distToCenter = dot(near->xyz, sphere->xyz) + near->w; - if (distToCenter < -sphere->w) { - return false; - } - distToCenter = dot(far->xyz, sphere->xyz) + far->w; - if (distToCenter < -sphere->w) { - return false; - } - return true; -} - - -///////////////////////////////////////////////////// -// int ops -///////////////////////////////////////////////////// -_RS_RUNTIME uint __attribute__((overloadable, always_inline)) rsClamp(uint amount, uint low, uint high); -_RS_RUNTIME int __attribute__((overloadable, always_inline)) rsClamp(int amount, int low, int high); -_RS_RUNTIME ushort __attribute__((overloadable, always_inline)) rsClamp(ushort amount, ushort low, ushort high); -_RS_RUNTIME short __attribute__((overloadable, always_inline)) rsClamp(short amount, short low, short high); -_RS_RUNTIME uchar __attribute__((overloadable, always_inline)) rsClamp(uchar amount, uchar low, uchar high); -_RS_RUNTIME char __attribute__((overloadable, always_inline)) rsClamp(char amount, char low, char high); #undef _RS_RUNTIME diff --git a/libs/rs/scriptc/rs_debug.rsh b/libs/rs/scriptc/rs_debug.rsh new file mode 100644 index 000000000000..074c28fe70ab --- /dev/null +++ b/libs/rs/scriptc/rs_debug.rsh @@ -0,0 +1,123 @@ +/* + * 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. + */ + +/** @file rs_debug.rsh + * \brief Utility debugging routines + * + * Routines intended to be used during application developement. These should + * not be used in shipping applications. All print a string and value pair to + * the standard log. + * + */ + +#ifndef __RS_DEBUG_RSH__ +#define __RS_DEBUG_RSH__ + + + +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, float); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, float, float); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, float, float, float); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, float, float, float, float); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, double); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, const rs_matrix4x4 *); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, const rs_matrix3x3 *); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, const rs_matrix2x2 *); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, int); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, uint); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, long); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, unsigned long); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, long long); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, unsigned long long); +/** + * Debug function. Prints a string and value to the log. + */ +extern void __attribute__((overloadable)) + rsDebug(const char *, const void *); +#define RS_DEBUG(a) rsDebug(#a, a) +#define RS_DEBUG_MARKER rsDebug(__FILE__, __LINE__) + + +/** + * Debug function. Prints a string and value to the log. + */ +_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float2 v); +/** + * Debug function. Prints a string and value to the log. + */ +_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float3 v); +/** + * Debug function. Prints a string and value to the log. + */ +_RS_RUNTIME void __attribute__((overloadable)) rsDebug(const char *s, float4 v); + +#endif diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh index 9a8a4e66a03d..00fd1b10f53f 100644 --- a/libs/rs/scriptc/rs_graphics.rsh +++ b/libs/rs/scriptc/rs_graphics.rsh @@ -1,3 +1,25 @@ +/* + * 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. + */ + +/** @file rs_graphics.rsh + * \brief Renderscript graphics API + * + * A set of graphics functions used by Renderscript. + * + */ #ifndef __RS_GRAPHICS_RSH__ #define __RS_GRAPHICS_RSH__ @@ -37,7 +59,7 @@ extern void __attribute__((overloadable)) rsgClearAllRenderTargets(void); /** - * Force RenderScript to finish all rendering commands + * Force Renderscript to finish all rendering commands */ extern uint __attribute__((overloadable)) rsgFinish(void); @@ -94,16 +116,38 @@ extern void __attribute__((overloadable)) extern void __attribute__((overloadable)) rsgBindTexture(rs_program_fragment, uint slot, rs_allocation); - +/** + * Load the projection matrix for a currently bound fixed function + * vertex program. Calling this function with a custom vertex shader + * would result in an error. + * @param proj projection matrix + */ extern void __attribute__((overloadable)) - rsgProgramVertexLoadProjectionMatrix(const rs_matrix4x4 *); + rsgProgramVertexLoadProjectionMatrix(const rs_matrix4x4 *proj); +/** + * Load the model matrix for a currently bound fixed function + * vertex program. Calling this function with a custom vertex shader + * would result in an error. + * @param model model matrix + */ extern void __attribute__((overloadable)) - rsgProgramVertexLoadModelMatrix(const rs_matrix4x4 *); + rsgProgramVertexLoadModelMatrix(const rs_matrix4x4 *model); +/** + * Load the texture matrix for a currently bound fixed function + * vertex program. Calling this function with a custom vertex shader + * would result in an error. + * @param tex texture matrix + */ extern void __attribute__((overloadable)) - rsgProgramVertexLoadTextureMatrix(const rs_matrix4x4 *); - + rsgProgramVertexLoadTextureMatrix(const rs_matrix4x4 *tex); +/** + * Get the projection matrix for a currently bound fixed function + * vertex program. Calling this function with a custom vertex shader + * would result in an error. + * @param proj matrix to store the current projection matrix into + */ extern void __attribute__((overloadable)) - rsgProgramVertexGetProjectionMatrix(rs_matrix4x4 *); + rsgProgramVertexGetProjectionMatrix(rs_matrix4x4 *proj); /** * Set the constant color for a fixed function emulation program. @@ -239,15 +283,29 @@ extern void __attribute__((overloadable)) rsgDrawSpriteScreenspace(float x, float y, float z, float w, float h); /** - * Draw a mesh of geometry using the current context state. The whole mesh is + * Draw a mesh using the current context state. The whole mesh is * rendered. * * @param ism */ extern void __attribute__((overloadable)) rsgDrawMesh(rs_mesh ism); +/** + * Draw part of a mesh using the current context state. + * @param ism mesh object to render + * @param primitiveIndex for meshes that contain multiple primitive groups + * this parameter specifies the index of the group to draw. + */ extern void __attribute__((overloadable)) rsgDrawMesh(rs_mesh ism, uint primitiveIndex); +/** + * Draw specified index range of part of a mesh using the current context state. + * @param ism mesh object to render + * @param primitiveIndex for meshes that contain multiple primitive groups + * this parameter specifies the index of the group to draw. + * @param start starting index in the range + * @param len number of indices to draw + */ extern void __attribute__((overloadable)) rsgDrawMesh(rs_mesh ism, uint primitiveIndex, uint start, uint len); @@ -264,29 +322,54 @@ extern void __attribute__((overloadable)) /** * Clears the depth suface to the specified value. - * */ extern void __attribute__((overloadable)) rsgClearDepth(float value); - +/** + * Draws text given a string and location + */ extern void __attribute__((overloadable)) rsgDrawText(const char *, int x, int y); +/** + * \overload + */ extern void __attribute__((overloadable)) rsgDrawText(rs_allocation, int x, int y); +/** + * Binds the font object to be used for all subsequent font rendering calls + * @param font object to bind + */ extern void __attribute__((overloadable)) - rsgBindFont(rs_font); + rsgBindFont(rs_font font); +/** + * Sets the font color for all subsequent rendering calls + * @param r red component + * @param g green component + * @param b blue component + * @param a alpha component + */ extern void __attribute__((overloadable)) - rsgFontColor(float, float, float, float); -// Returns the bounding box of the text relative to (0, 0) -// Any of left, right, top, bottom could be NULL + rsgFontColor(float r, float g, float b, float a); +/** + * Returns the bounding box of the text relative to (0, 0) + * Any of left, right, top, bottom could be NULL + */ extern void __attribute__((overloadable)) rsgMeasureText(const char *, int *left, int *right, int *top, int *bottom); +/** + * \overload + */ extern void __attribute__((overloadable)) rsgMeasureText(rs_allocation, int *left, int *right, int *top, int *bottom); - +/** + * Computes an axis aligned bounding box of a mesh object + */ extern void __attribute__((overloadable)) rsgMeshComputeBoundingBox(rs_mesh mesh, float *minX, float *minY, float *minZ, float *maxX, float *maxY, float *maxZ); +/** + * \overload + */ __inline__ static void __attribute__((overloadable, always_inline)) rsgMeshComputeBoundingBox(rs_mesh mesh, float3 *bBoxMin, float3 *bBoxMax) { float x1, y1, z1, x2, y2, z2; diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh index 1d36cc6530aa..8117ca824b18 100644 --- a/libs/rs/scriptc/rs_math.rsh +++ b/libs/rs/scriptc/rs_math.rsh @@ -1,495 +1,248 @@ -#ifndef __RS_MATH_RSH__ -#define __RS_MATH_RSH__ - -/** - * Copy reference to the specified object. - * - * @param dst - * @param src - */ -extern void __attribute__((overloadable)) - rsSetObject(rs_element *dst, rs_element src); -extern void __attribute__((overloadable)) - rsSetObject(rs_type *dst, rs_type src); -extern void __attribute__((overloadable)) - rsSetObject(rs_allocation *dst, rs_allocation src); -extern void __attribute__((overloadable)) - rsSetObject(rs_sampler *dst, rs_sampler src); -extern void __attribute__((overloadable)) - rsSetObject(rs_script *dst, rs_script src); -extern void __attribute__((overloadable)) - rsSetObject(rs_mesh *dst, rs_mesh src); -extern void __attribute__((overloadable)) - rsSetObject(rs_program_fragment *dst, rs_program_fragment src); -extern void __attribute__((overloadable)) - rsSetObject(rs_program_vertex *dst, rs_program_vertex src); -extern void __attribute__((overloadable)) - rsSetObject(rs_program_raster *dst, rs_program_raster src); -extern void __attribute__((overloadable)) - rsSetObject(rs_program_store *dst, rs_program_store src); -extern void __attribute__((overloadable)) - rsSetObject(rs_font *dst, rs_font src); - -/** - * Sets the object to NULL. +/* + * Copyright (C) 2011 The Android Open Source Project * - * @return bool - */ -extern void __attribute__((overloadable)) - rsClearObject(rs_element *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_type *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_allocation *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_sampler *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_script *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_mesh *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_program_fragment *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_program_vertex *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_program_raster *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_program_store *dst); -extern void __attribute__((overloadable)) - rsClearObject(rs_font *dst); - -/** - * Tests if the object is valid. Returns true if the object is valid, false if - * it is NULL. - * - * @return bool - */ -extern bool __attribute__((overloadable)) - rsIsObject(rs_element); -extern bool __attribute__((overloadable)) - rsIsObject(rs_type); -extern bool __attribute__((overloadable)) - rsIsObject(rs_allocation); -extern bool __attribute__((overloadable)) - rsIsObject(rs_sampler); -extern bool __attribute__((overloadable)) - rsIsObject(rs_script); -extern bool __attribute__((overloadable)) - rsIsObject(rs_mesh); -extern bool __attribute__((overloadable)) - rsIsObject(rs_program_fragment); -extern bool __attribute__((overloadable)) - rsIsObject(rs_program_vertex); -extern bool __attribute__((overloadable)) - rsIsObject(rs_program_raster); -extern bool __attribute__((overloadable)) - rsIsObject(rs_program_store); -extern bool __attribute__((overloadable)) - rsIsObject(rs_font); - - -/** - * Returns the Allocation for a given pointer. The pointer should point within - * a valid allocation. The results are undefined if the pointer is not from a - * valid allocation. - */ -extern rs_allocation __attribute__((overloadable)) - rsGetAllocation(const void *); - -/** - * Query the dimension of an allocation. + * 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 * - * @return uint32_t The X dimension of the allocation. - */ -extern uint32_t __attribute__((overloadable)) - rsAllocationGetDimX(rs_allocation); - -/** - * Query the dimension of an allocation. + * http://www.apache.org/licenses/LICENSE-2.0 * - * @return uint32_t The Y dimension of the allocation. + * 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. */ -extern uint32_t __attribute__((overloadable)) - rsAllocationGetDimY(rs_allocation); -/** - * Query the dimension of an allocation. +/** @file rs_math.rsh + * \brief todo-jsams * - * @return uint32_t The Z dimension of the allocation. - */ -extern uint32_t __attribute__((overloadable)) - rsAllocationGetDimZ(rs_allocation); - -/** - * Query an allocation for the presence of more than one LOD. + * todo-jsams * - * @return uint32_t Returns 1 if more than one LOD is present, 0 otherwise. */ -extern uint32_t __attribute__((overloadable)) - rsAllocationGetDimLOD(rs_allocation); -/** - * Query an allocation for the presence of more than one face. - * - * @return uint32_t Returns 1 if more than one face is present, 0 otherwise. - */ -extern uint32_t __attribute__((overloadable)) - rsAllocationGetDimFaces(rs_allocation); +#ifndef __RS_MATH_RSH__ +#define __RS_MATH_RSH__ -/** - * Copy part of an allocation from another allocation. - * - * @param dstAlloc Allocation to copy data into. - * @param dstOff The offset of the first element to be copied in - * the destination allocation. - * @param dstMip Mip level in the destination allocation. - * @param count The number of elements to be copied. - * @param srcAlloc The source data allocation. - * @param srcOff The offset of the first element in data to be - * copied in the source allocation. - * @param srcMip Mip level in the source allocation. - */ -extern void __attribute__((overloadable)) - rsAllocationCopy1DRange(rs_allocation dstAlloc, - uint32_t dstOff, uint32_t dstMip, - uint32_t count, - rs_allocation srcAlloc, - uint32_t srcOff, uint32_t srcMip); /** - * Copy a rectangular region into the allocation from another - * allocation. - * - * @param dstAlloc allocation to copy data into. - * @param dstXoff X offset of the region to update in the - * destination allocation. - * @param dstYoff Y offset of the region to update in the - * destination allocation. - * @param dstMip Mip level in the destination allocation. - * @param dstFace Cubemap face of the destination allocation, - * ignored for allocations that aren't cubemaps. - * @param width Width of the incoming region to update. - * @param height Height of the incoming region to update. - * @param srcAlloc The source data allocation. - * @param srcXoff X offset in data of the source allocation. - * @param srcYoff Y offset in data of the source allocation. - * @param srcMip Mip level in the source allocation. - * @param srcFace Cubemap face of the source allocation, - * ignored for allocations that aren't cubemaps. + * Return a random value between 0 (or min_value) and max_malue. */ -extern void __attribute__((overloadable)) - rsAllocationCopy2DRange(rs_allocation dstAlloc, - uint32_t dstXoff, uint32_t dstYoff, - uint32_t dstMip, - rs_allocation_cubemap_face dstFace, - uint32_t width, uint32_t height, - rs_allocation srcAlloc, - uint32_t srcXoff, uint32_t srcYoff, - uint32_t srcMip, - rs_allocation_cubemap_face srcFace); - -// Extract a single element from an allocation. -extern const void * __attribute__((overloadable)) - rsGetElementAt(rs_allocation, uint32_t x); -extern const void * __attribute__((overloadable)) - rsGetElementAt(rs_allocation, uint32_t x, uint32_t y); -extern const void * __attribute__((overloadable)) - rsGetElementAt(rs_allocation, uint32_t x, uint32_t y, uint32_t z); - -// Return a random value between 0 (or min_value) and max_malue. extern int __attribute__((overloadable)) rsRand(int max_value); +/** + * \overload + */ extern int __attribute__((overloadable)) rsRand(int min_value, int max_value); +/** + * \overload + */ extern float __attribute__((overloadable)) rsRand(float max_value); +/** + * \overload + */ extern float __attribute__((overloadable)) rsRand(float min_value, float max_value); -// return the fractional part of a float -// min(v - ((int)floor(v)), 0x1.fffffep-1f); +/** + * Returns the fractional part of a float + */ extern float __attribute__((overloadable)) rsFrac(float); -// Send a message back to the client. Will not block and returns true -// if the message was sendable and false if the fifo was full. -// A message ID is required. Data payload is optional. -extern bool __attribute__((overloadable)) - rsSendToClient(int cmdID); -extern bool __attribute__((overloadable)) - rsSendToClient(int cmdID, const void *data, uint len); - -// Send a message back to the client, blocking until the message is queued. -// A message ID is required. Data payload is optional. -extern void __attribute__((overloadable)) - rsSendToClientBlocking(int cmdID); -extern void __attribute__((overloadable)) - rsSendToClientBlocking(int cmdID, const void *data, uint len); - - -// Script to Script -enum rs_for_each_strategy { - RS_FOR_EACH_STRATEGY_SERIAL, - RS_FOR_EACH_STRATEGY_DONT_CARE, - RS_FOR_EACH_STRATEGY_DST_LINEAR, - RS_FOR_EACH_STRATEGY_TILE_SMALL, - RS_FOR_EACH_STRATEGY_TILE_MEDIUM, - RS_FOR_EACH_STRATEGY_TILE_LARGE -}; - -typedef struct rs_script_call { - enum rs_for_each_strategy strategy; - uint32_t xStart; - uint32_t xEnd; - uint32_t yStart; - uint32_t yEnd; - uint32_t zStart; - uint32_t zEnd; - uint32_t arrayStart; - uint32_t arrayEnd; -} rs_script_call_t; -#if !defined(RS_VERSION) || (RS_VERSION < 14) -extern void __attribute__((overloadable)) - rsForEach(rs_script script, rs_allocation input, - rs_allocation output, const void * usrData, - const rs_script_call_t *); +///////////////////////////////////////////////////// +// int ops +///////////////////////////////////////////////////// -extern void __attribute__((overloadable)) - rsForEach(rs_script script, rs_allocation input, - rs_allocation output, const void * usrData); -#else -extern void __attribute__((overloadable)) - rsForEach(rs_script script, rs_allocation input, rs_allocation output); - -extern void __attribute__((overloadable)) - rsForEach(rs_script script, rs_allocation input, rs_allocation output, - const void * usrData, size_t usrDataLen); - -extern void __attribute__((overloadable)) - rsForEach(rs_script script, rs_allocation input, rs_allocation output, - const void * usrData, size_t usrDataLen, const rs_script_call_t *); -#endif - - -/** - * Atomic add one to the value at addr. - * Equal to rsAtomicAdd(addr, 1) - * - * @param addr Address of value to increment - * - * @return old value - */ -extern int32_t __attribute__((overloadable)) - rsAtomicInc(volatile int32_t* addr); /** - * Atomic add one to the value at addr. - * Equal to rsAtomicAdd(addr, 1) - * - * @param addr Address of value to increment + * Clamp the value amount between low and high. * - * @return old value + * @param amount The value to clamp + * @param low + * @param high */ -extern uint32_t __attribute__((overloadable)) - rsAtomicInc(volatile uint32_t* addr); +_RS_RUNTIME uint __attribute__((overloadable, always_inline)) rsClamp(uint amount, uint low, uint high); /** - * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1) - * - * @param addr Address of value to decrement - * - * @return old value - */ -extern int32_t __attribute__((overloadable)) - rsAtomicDec(volatile int32_t* addr); -/** - * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1) - * - * @param addr Address of value to decrement - * - * @return old value + * \overload */ -extern uint32_t __attribute__((overloadable)) - rsAtomicDec(volatile uint32_t* addr); - +_RS_RUNTIME int __attribute__((overloadable, always_inline)) rsClamp(int amount, int low, int high); /** - * Atomic add a value to the value at addr. addr[0] += value - * - * @param addr Address of value to modify - * @param value Amount to add to the value at addr - * - * @return old value + * \overload */ -extern int32_t __attribute__((overloadable)) - rsAtomicAdd(volatile int32_t* addr, int32_t value); +_RS_RUNTIME ushort __attribute__((overloadable, always_inline)) rsClamp(ushort amount, ushort low, ushort high); /** - * Atomic add a value to the value at addr. addr[0] += value - * - * @param addr Address of value to modify - * @param value Amount to add to the value at addr - * - * @return old value + * \overload */ -extern uint32_t __attribute__((overloadable)) - rsAtomicAdd(volatile uint32_t* addr, uint32_t value); +_RS_RUNTIME short __attribute__((overloadable, always_inline)) rsClamp(short amount, short low, short high); +/** + * \overload + */ +_RS_RUNTIME uchar __attribute__((overloadable, always_inline)) rsClamp(uchar amount, uchar low, uchar high); +/** + * \overload + */ +_RS_RUNTIME char __attribute__((overloadable, always_inline)) rsClamp(char amount, char low, char high); + + +/** + * Computes 6 frustum planes from the view projection matrix + * @param viewProj matrix to extract planes from + * @param left plane + * @param right plane + * @param top plane + * @param bottom plane + * @param near plane + * @param far plane + */ +__inline__ static void __attribute__((overloadable, always_inline)) +rsExtractFrustumPlanes(const rs_matrix4x4 *viewProj, + float4 *left, float4 *right, + float4 *top, float4 *bottom, + float4 *near, float4 *far) { + // x y z w = a b c d in the plane equation + left->x = viewProj->m[3] + viewProj->m[0]; + left->y = viewProj->m[7] + viewProj->m[4]; + left->z = viewProj->m[11] + viewProj->m[8]; + left->w = viewProj->m[15] + viewProj->m[12]; -/** - * Atomic Subtract a value from the value at addr. addr[0] -= value - * - * @param addr Address of value to modify - * @param value Amount to subtract from the value at addr - * - * @return old value - */ -extern int32_t __attribute__((overloadable)) - rsAtomicSub(volatile int32_t* addr, int32_t value); -/** - * Atomic Subtract a value from the value at addr. addr[0] -= value - * - * @param addr Address of value to modify - * @param value Amount to subtract from the value at addr - * - * @return old value - */ -extern uint32_t __attribute__((overloadable)) - rsAtomicSub(volatile uint32_t* addr, uint32_t value); + right->x = viewProj->m[3] - viewProj->m[0]; + right->y = viewProj->m[7] - viewProj->m[4]; + right->z = viewProj->m[11] - viewProj->m[8]; + right->w = viewProj->m[15] - viewProj->m[12]; -/** - * Atomic Bitwise and a value from the value at addr. addr[0] &= value - * - * @param addr Address of value to modify - * @param value Amount to and with the value at addr - * - * @return old value - */ -extern int32_t __attribute__((overloadable)) - rsAtomicAnd(volatile int32_t* addr, int32_t value); -/** - * Atomic Bitwise and a value from the value at addr. addr[0] &= value - * - * @param addr Address of value to modify - * @param value Amount to and with the value at addr - * - * @return old value - */ -extern uint32_t __attribute__((overloadable)) - rsAtomicAnd(volatile uint32_t* addr, uint32_t value); + top->x = viewProj->m[3] - viewProj->m[1]; + top->y = viewProj->m[7] - viewProj->m[5]; + top->z = viewProj->m[11] - viewProj->m[9]; + top->w = viewProj->m[15] - viewProj->m[13]; -/** - * Atomic Bitwise or a value from the value at addr. addr[0] |= value - * - * @param addr Address of value to modify - * @param value Amount to or with the value at addr - * - * @return old value - */ -extern int32_t __attribute__((overloadable)) - rsAtomicOr(volatile int32_t* addr, int32_t value); -/** - * Atomic Bitwise or a value from the value at addr. addr[0] |= value - * - * @param addr Address of value to modify - * @param value Amount to or with the value at addr - * - * @return old value - */ -extern uint32_t __attribute__((overloadable)) - rsAtomicOr(volatile uint32_t* addr, uint32_t value); + bottom->x = viewProj->m[3] + viewProj->m[1]; + bottom->y = viewProj->m[7] + viewProj->m[5]; + bottom->z = viewProj->m[11] + viewProj->m[9]; + bottom->w = viewProj->m[15] + viewProj->m[13]; -/** - * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value - * - * @param addr Address of value to modify - * @param value Amount to xor with the value at addr - * - * @return old value - */ -extern uint32_t __attribute__((overloadable)) - rsAtomicXor(volatile uint32_t* addr, uint32_t value); -/** - * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value - * - * @param addr Address of value to modify - * @param value Amount to xor with the value at addr - * - * @return old value - */ -extern int32_t __attribute__((overloadable)) - rsAtomicXor(volatile int32_t* addr, int32_t value); + near->x = viewProj->m[3] + viewProj->m[2]; + near->y = viewProj->m[7] + viewProj->m[6]; + near->z = viewProj->m[11] + viewProj->m[10]; + near->w = viewProj->m[15] + viewProj->m[14]; + + far->x = viewProj->m[3] - viewProj->m[2]; + far->y = viewProj->m[7] - viewProj->m[6]; + far->z = viewProj->m[11] - viewProj->m[10]; + far->w = viewProj->m[15] - viewProj->m[14]; + + float len = length(left->xyz); + *left /= len; + len = length(right->xyz); + *right /= len; + len = length(top->xyz); + *top /= len; + len = length(bottom->xyz); + *bottom /= len; + len = length(near->xyz); + *near /= len; + len = length(far->xyz); + *far /= len; +} /** - * Atomic Set the value at addr to the min of addr and value - * addr[0] = rsMin(addr[0], value) - * - * @param addr Address of value to modify - * @param value comparison value - * - * @return old value + * Checks if a sphere is withing the 6 frustum planes + * @param sphere float4 representing the sphere + * @param left plane + * @param right plane + * @param top plane + * @param bottom plane + * @param near plane + * @param far plane */ -extern uint32_t __attribute__((overloadable)) - rsAtomicMin(volatile uint32_t* addr, uint32_t value); +__inline__ static bool __attribute__((overloadable, always_inline)) +rsIsSphereInFrustum(float4 *sphere, + float4 *left, float4 *right, + float4 *top, float4 *bottom, + float4 *near, float4 *far) { + + float distToCenter = dot(left->xyz, sphere->xyz) + left->w; + if (distToCenter < -sphere->w) { + return false; + } + distToCenter = dot(right->xyz, sphere->xyz) + right->w; + if (distToCenter < -sphere->w) { + return false; + } + distToCenter = dot(top->xyz, sphere->xyz) + top->w; + if (distToCenter < -sphere->w) { + return false; + } + distToCenter = dot(bottom->xyz, sphere->xyz) + bottom->w; + if (distToCenter < -sphere->w) { + return false; + } + distToCenter = dot(near->xyz, sphere->xyz) + near->w; + if (distToCenter < -sphere->w) { + return false; + } + distToCenter = dot(far->xyz, sphere->xyz) + far->w; + if (distToCenter < -sphere->w) { + return false; + } + return true; +} + + /** - * Atomic Set the value at addr to the min of addr and value - * addr[0] = rsMin(addr[0], value) + * Pack floating point (0-1) RGB values into a uchar4. The alpha component is + * set to 255 (1.0). * - * @param addr Address of value to modify - * @param value comparison value + * @param r + * @param g + * @param b * - * @return old value + * @return uchar4 */ -extern int32_t __attribute__((overloadable)) - rsAtomicMin(volatile int32_t* addr, int32_t value); +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b); /** - * Atomic Set the value at addr to the max of addr and value - * addr[0] = rsMax(addr[0], value) + * Pack floating point (0-1) RGBA values into a uchar4. * - * @param addr Address of value to modify - * @param value comparison value + * @param r + * @param g + * @param b + * @param a * - * @return old value + * @return uchar4 */ -extern uint32_t __attribute__((overloadable)) - rsAtomicMax(volatile uint32_t* addr, uint32_t value); +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float r, float g, float b, float a); + /** - * Atomic Set the value at addr to the max of addr and value - * addr[0] = rsMin(addr[0], value) + * Pack floating point (0-1) RGB values into a uchar4. The alpha component is + * set to 255 (1.0). * - * @param addr Address of value to modify - * @param value comparison value + * @param color * - * @return old value + * @return uchar4 */ -extern int32_t __attribute__((overloadable)) - rsAtomicMax(volatile int32_t* addr, int32_t value); +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float3 color); /** - * Compare-and-set operation with a full memory barrier. - * - * If the value at addr matches compareValue then newValue is written. + * Pack floating point (0-1) RGBA values into a uchar4. * - * @param addr The address to compare and replace if the compare passes. - * @param compareValue The value to test addr[0] against. - * @param newValue The value to write if the test passes. + * @param color * - * @return old value + * @return uchar4 */ -extern int32_t __attribute__((overloadable)) - rsAtomicCas(volatile int32_t* addr, int32_t compareValue, int32_t newValue); +_RS_RUNTIME uchar4 __attribute__((overloadable)) rsPackColorTo8888(float4 color); /** - * Compare-and-set operation with a full memory barrier. - * - * If the value at addr matches compareValue then newValue is written. + * Unpack a uchar4 color to float4. The resulting float range will be (0-1). * - * @param addr The address to compare and replace if the compare passes. - * @param compareValue The value to test addr[0] against. - * @param newValue The value to write if the test passes. + * @param c * - * @return old value + * @return float4 */ -extern uint32_t __attribute__((overloadable)) - rsAtomicCas(volatile uint32_t* addr, int32_t compareValue, int32_t newValue); +_RS_RUNTIME float4 rsUnpackColor8888(uchar4 c); #endif diff --git a/libs/rs/scriptc/rs_matrix.rsh b/libs/rs/scriptc/rs_matrix.rsh new file mode 100644 index 000000000000..ab3cd3b25a6e --- /dev/null +++ b/libs/rs/scriptc/rs_matrix.rsh @@ -0,0 +1,378 @@ +/* + * 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. + */ + +/** @file rs_matrix.rsh + * \brief Matrix routines + * + * + */ + +#ifndef __RS_MATRIX_RSH__ +#define __RS_MATRIX_RSH__ + +/** + * Set one element of a matrix. + * + * @param m The matrix to be set + * @param row + * @param col + * @param v + * + * @return void + */ +_RS_RUNTIME void __attribute__((overloadable)) +rsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v); +/** + * \overload + */ +_RS_RUNTIME void __attribute__((overloadable)) +rsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v); +/** + * \overload + */ +_RS_RUNTIME void __attribute__((overloadable)) +rsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v); + +/** + * Get one element of a matrix. + * + * @param m The matrix to read from + * @param row + * @param col + * + * @return float + */ +_RS_RUNTIME float __attribute__((overloadable)) +rsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col); +/** + * \overload + */ +_RS_RUNTIME float __attribute__((overloadable)) +rsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col); +/** + * \overload + */ +_RS_RUNTIME float __attribute__((overloadable)) +rsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col); + +/** + * Set the elements of a matrix to the identity matrix. + * + * @param m + */ +extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix4x4 *m); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix3x3 *m); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoadIdentity(rs_matrix2x2 *m); + +/** + * Set the elements of a matrix from an array of floats. + * + * @param m + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const float *v); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix3x3 *m, const float *v); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix2x2 *m, const float *v); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix4x4 *v); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix3x3 *v); + +/** + * Set the elements of a matrix from another matrix. + * + * @param m + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix4x4 *m, const rs_matrix2x2 *v); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix3x3 *m, const rs_matrix3x3 *v); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixLoad(rs_matrix2x2 *m, const rs_matrix2x2 *v); + +/** + * Load a rotation matrix. + * + * @param m + * @param rot + * @param x + * @param y + * @param z + */ +extern void __attribute__((overloadable)) +rsMatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z); + +/** + * Load a scale matrix. + * + * @param m + * @param x + * @param y + * @param z + */ +extern void __attribute__((overloadable)) +rsMatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z); + +/** + * Load a translation matrix. + * + * @param m + * @param x + * @param y + * @param z + */ +extern void __attribute__((overloadable)) +rsMatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z); + +/** + * Multiply two matrix (lhs, rhs) and place the result in m. + * + * @param m + * @param lhs + * @param rhs + */ +extern void __attribute__((overloadable)) +rsMatrixLoadMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs); +/** + * \overload + */ +extern void __attribute__((overloadable)) +rsMatrixLoadMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs); +/** + * \overload + */ +extern void __attribute__((overloadable)) +rsMatrixLoadMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs); + +/** + * Multiply the matrix m by rhs and place the result back into m. + * + * @param m (lhs) + * @param rhs + */ +extern void __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, const rs_matrix4x4 *rhs); +/** + * \overload + */ +extern void __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix3x3 *m, const rs_matrix3x3 *rhs); +/** + * \overload + */ +extern void __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix2x2 *m, const rs_matrix2x2 *rhs); + +/** + * Multiple matrix m with a rotation matrix + * + * @param m + * @param rot + * @param x + * @param y + * @param z + */ +extern void __attribute__((overloadable)) +rsMatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z); + +/** + * Multiple matrix m with a scale matrix + * + * @param m + * @param x + * @param y + * @param z + */ +extern void __attribute__((overloadable)) +rsMatrixScale(rs_matrix4x4 *m, float x, float y, float z); + +/** + * Multiple matrix m with a translation matrix + * + * @param m + * @param x + * @param y + * @param z + */ +extern void __attribute__((overloadable)) +rsMatrixTranslate(rs_matrix4x4 *m, float x, float y, float z); + +/** + * Load an Ortho projection matrix constructed from the 6 planes + * + * @param m + * @param left + * @param right + * @param bottom + * @param top + * @param near + * @param far + */ +extern void __attribute__((overloadable)) +rsMatrixLoadOrtho(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far); + +/** + * Load an Frustum projection matrix constructed from the 6 planes + * + * @param m + * @param left + * @param right + * @param bottom + * @param top + * @param near + * @param far + */ +extern void __attribute__((overloadable)) +rsMatrixLoadFrustum(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far); + +/** + * Load an perspective projection matrix constructed from the 6 planes + * + * @param m + * @param fovy Field of view, in degrees along the Y axis. + * @param aspect Ratio of x / y. + * @param near + * @param far + */ +extern void __attribute__((overloadable)) +rsMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far); + +#if !defined(RS_VERSION) || (RS_VERSION < 14) +/** + * Multiply a vector by a matrix and return the result vector. + * API version 10-13 + */ +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, float4 in); + +/** + * \overload + */ +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, float3 in); + +/** + * \overload + */ +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix4x4 *m, float2 in); + +/** + * \overload + */ +_RS_RUNTIME float3 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix3x3 *m, float3 in); + +/** + * \overload + */ +_RS_RUNTIME float3 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix3x3 *m, float2 in); + +/** + * \overload + */ +_RS_RUNTIME float2 __attribute__((overloadable)) +rsMatrixMultiply(rs_matrix2x2 *m, float2 in); +#else +/** + * Multiply a vector by a matrix and return the result vector. + * API version 10-13 + */ +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(const rs_matrix4x4 *m, float4 in); + +/** + * \overload + */ +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(const rs_matrix4x4 *m, float3 in); + +/** + * \overload + */ +_RS_RUNTIME float4 __attribute__((overloadable)) +rsMatrixMultiply(const rs_matrix4x4 *m, float2 in); + +/** + * \overload + */ +_RS_RUNTIME float3 __attribute__((overloadable)) +rsMatrixMultiply(const rs_matrix3x3 *m, float3 in); + +/** + * \overload + */ +_RS_RUNTIME float3 __attribute__((overloadable)) +rsMatrixMultiply(const rs_matrix3x3 *m, float2 in); + +/** + * \overload + */ +_RS_RUNTIME float2 __attribute__((overloadable)) +rsMatrixMultiply(const rs_matrix2x2 *m, float2 in); +#endif + + +/** + * Returns true if the matrix was successfully inversed + * + * @param m + */ +extern bool __attribute__((overloadable)) rsMatrixInverse(rs_matrix4x4 *m); + +/** + * Returns true if the matrix was successfully inversed and transposed. + * + * @param m + */ +extern bool __attribute__((overloadable)) rsMatrixInverseTranspose(rs_matrix4x4 *m); + +/** + * Transpose the matrix m. + * + * @param m + */ +extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix4x4 *m); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix3x3 *m); +/** + * \overload + */ +extern void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix2x2 *m); + + +#endif diff --git a/libs/rs/scriptc/rs_object.rsh b/libs/rs/scriptc/rs_object.rsh new file mode 100644 index 000000000000..a43121937ea8 --- /dev/null +++ b/libs/rs/scriptc/rs_object.rsh @@ -0,0 +1,205 @@ +/* + * 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. + */ + +/** @file rs_object.rsh + * \brief Object routines + * + * + */ + +#ifndef __RS_OBJECT_RSH__ +#define __RS_OBJECT_RSH__ + + +/** + * Copy reference to the specified object. + * + * @param dst + * @param src + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_element *dst, rs_element src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_type *dst, rs_type src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_allocation *dst, rs_allocation src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_sampler *dst, rs_sampler src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_script *dst, rs_script src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_mesh *dst, rs_mesh src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_program_fragment *dst, rs_program_fragment src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_program_vertex *dst, rs_program_vertex src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_program_raster *dst, rs_program_raster src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_program_store *dst, rs_program_store src); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsSetObject(rs_font *dst, rs_font src); + +/** + * Sets the object to NULL. + * + * @return bool + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_element *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_type *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_allocation *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_sampler *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_script *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_mesh *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_program_fragment *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_program_vertex *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_program_raster *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_program_store *dst); +/** + * \overload + */ +extern void __attribute__((overloadable)) + rsClearObject(rs_font *dst); + + + +/** + * Tests if the object is valid. Returns true if the object is valid, false if + * it is NULL. + * + * @return bool + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_element); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_type); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_allocation); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_sampler); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_script); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_mesh); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_fragment); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_vertex); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_raster); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_program_store); +/** + * \overload + */ +extern bool __attribute__((overloadable)) + rsIsObject(rs_font); + +#endif diff --git a/libs/rs/scriptc/rs_quaternion.rsh b/libs/rs/scriptc/rs_quaternion.rsh new file mode 100644 index 000000000000..36e6736c6c6f --- /dev/null +++ b/libs/rs/scriptc/rs_quaternion.rsh @@ -0,0 +1,257 @@ +/* + * 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. + */ + +/** @file rs_matrix.rsh + * \brief Quaternion routines + * + * + */ + +#ifndef __RS_QUATERNION_RSH__ +#define __RS_QUATERNION_RSH__ + + +/** + * Set the quaternion components + * @param w component + * @param x component + * @param y component + * @param z component + */ +static void __attribute__((overloadable)) +rsQuaternionSet(rs_quaternion *q, float w, float x, float y, float z) { + q->w = w; + q->x = x; + q->y = y; + q->z = z; +} + +/** + * Set the quaternion from another quaternion + * @param q destination quaternion + * @param rhs source quaternion + */ +static void __attribute__((overloadable)) +rsQuaternionSet(rs_quaternion *q, const rs_quaternion *rhs) { + q->w = rhs->w; + q->x = rhs->x; + q->y = rhs->y; + q->z = rhs->z; +} + +/** + * Multiply quaternion by a scalar + * @param q quaternion to multiply + * @param s scalar + */ +static void __attribute__((overloadable)) +rsQuaternionMultiply(rs_quaternion *q, float s) { + q->w *= s; + q->x *= s; + q->y *= s; + q->z *= s; +} + +/** + * Multiply quaternion by another quaternion + * @param q destination quaternion + * @param rhs right hand side quaternion to multiply by + */ +static void __attribute__((overloadable)) +rsQuaternionMultiply(rs_quaternion *q, const rs_quaternion *rhs) { + q->w = -q->x*rhs->x - q->y*rhs->y - q->z*rhs->z + q->w*rhs->w; + q->x = q->x*rhs->w + q->y*rhs->z - q->z*rhs->y + q->w*rhs->x; + q->y = -q->x*rhs->z + q->y*rhs->w + q->z*rhs->x + q->w*rhs->y; + q->z = q->x*rhs->y - q->y*rhs->x + q->z*rhs->w + q->w*rhs->z; +} + +/** + * Add two quaternions + * @param q destination quaternion to add to + * @param rsh right hand side quaternion to add + */ +static void +rsQuaternionAdd(rs_quaternion *q, const rs_quaternion *rhs) { + q->w *= rhs->w; + q->x *= rhs->x; + q->y *= rhs->y; + q->z *= rhs->z; +} + +/** + * Loads a quaternion that represents a rotation about an arbitrary unit vector + * @param q quaternion to set + * @param rot angle to rotate by + * @param x component of a vector + * @param y component of a vector + * @param x component of a vector + */ +static void +rsQuaternionLoadRotateUnit(rs_quaternion *q, float rot, float x, float y, float z) { + rot *= (float)(M_PI / 180.0f) * 0.5f; + float c = cos(rot); + float s = sin(rot); + + q->w = c; + q->x = x * s; + q->y = y * s; + q->z = z * s; +} + +/** + * Loads a quaternion that represents a rotation about an arbitrary vector + * (doesn't have to be unit) + * @param q quaternion to set + * @param rot angle to rotate by + * @param x component of a vector + * @param y component of a vector + * @param x component of a vector + */ +static void +rsQuaternionLoadRotate(rs_quaternion *q, float rot, float x, float y, float z) { + const float len = x*x + y*y + z*z; + if (len != 1) { + const float recipLen = 1.f / sqrt(len); + x *= recipLen; + y *= recipLen; + z *= recipLen; + } + rsQuaternionLoadRotateUnit(q, rot, x, y, z); +} + +/** + * Conjugates the quaternion + * @param q quaternion to conjugate + */ +static void +rsQuaternionConjugate(rs_quaternion *q) { + q->x = -q->x; + q->y = -q->y; + q->z = -q->z; +} + +/** + * Dot product of two quaternions + * @param q0 first quaternion + * @param q1 second quaternion + * @return dot product between q0 and q1 + */ +static float +rsQuaternionDot(const rs_quaternion *q0, const rs_quaternion *q1) { + return q0->w*q1->w + q0->x*q1->x + q0->y*q1->y + q0->z*q1->z; +} + +/** + * Normalizes the quaternion + * @param q quaternion to normalize + */ +static void +rsQuaternionNormalize(rs_quaternion *q) { + const float len = rsQuaternionDot(q, q); + if (len != 1) { + const float recipLen = 1.f / sqrt(len); + rsQuaternionMultiply(q, recipLen); + } +} + +/** + * Performs spherical linear interpolation between two quaternions + * @param q result quaternion from interpolation + * @param q0 first param + * @param q1 second param + * @param t how much to interpolate by + */ +static void +rsQuaternionSlerp(rs_quaternion *q, const rs_quaternion *q0, const rs_quaternion *q1, float t) { + if (t <= 0.0f) { + rsQuaternionSet(q, q0); + return; + } + if (t >= 1.0f) { + rsQuaternionSet(q, q1); + return; + } + + rs_quaternion tempq0, tempq1; + rsQuaternionSet(&tempq0, q0); + rsQuaternionSet(&tempq1, q1); + + float angle = rsQuaternionDot(q0, q1); + if (angle < 0) { + rsQuaternionMultiply(&tempq0, -1.0f); + angle *= -1.0f; + } + + float scale, invScale; + if (angle + 1.0f > 0.05f) { + if (1.0f - angle >= 0.05f) { + float theta = acos(angle); + float invSinTheta = 1.0f / sin(theta); + scale = sin(theta * (1.0f - t)) * invSinTheta; + invScale = sin(theta * t) * invSinTheta; + } else { + scale = 1.0f - t; + invScale = t; + } + } else { + rsQuaternionSet(&tempq1, tempq0.z, -tempq0.y, tempq0.x, -tempq0.w); + scale = sin(M_PI * (0.5f - t)); + invScale = sin(M_PI * t); + } + + rsQuaternionSet(q, tempq0.w*scale + tempq1.w*invScale, tempq0.x*scale + tempq1.x*invScale, + tempq0.y*scale + tempq1.y*invScale, tempq0.z*scale + tempq1.z*invScale); +} + +/** + * Computes rotation matrix from the normalized quaternion + * @param m resulting matrix + * @param p normalized quaternion + */ +static void rsQuaternionGetMatrixUnit(rs_matrix4x4 *m, const rs_quaternion *q) { + float x2 = 2.0f * q->x * q->x; + float y2 = 2.0f * q->y * q->y; + float z2 = 2.0f * q->z * q->z; + float xy = 2.0f * q->x * q->y; + float wz = 2.0f * q->w * q->z; + float xz = 2.0f * q->x * q->z; + float wy = 2.0f * q->w * q->y; + float wx = 2.0f * q->w * q->x; + float yz = 2.0f * q->y * q->z; + + m->m[0] = 1.0f - y2 - z2; + m->m[1] = xy - wz; + m->m[2] = xz + wy; + m->m[3] = 0.0f; + + m->m[4] = xy + wz; + m->m[5] = 1.0f - x2 - z2; + m->m[6] = yz - wx; + m->m[7] = 0.0f; + + m->m[8] = xz - wy; + m->m[9] = yz - wx; + m->m[10] = 1.0f - x2 - y2; + m->m[11] = 0.0f; + + m->m[12] = 0.0f; + m->m[13] = 0.0f; + m->m[14] = 0.0f; + m->m[15] = 1.0f; +} + +#endif + diff --git a/libs/rs/scriptc/rs_time.rsh b/libs/rs/scriptc/rs_time.rsh index f1abed6308e4..f8f297d32a18 100644 --- a/libs/rs/scriptc/rs_time.rsh +++ b/libs/rs/scriptc/rs_time.rsh @@ -1,3 +1,25 @@ +/* + * 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. + */ + +/** @file rs_time.rsh + * \brief Time routines + * + * + */ + #ifndef __RS_TIME_RSH__ #define __RS_TIME_RSH__ diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh index 121e013cf0ee..875beb9b196d 100644 --- a/libs/rs/scriptc/rs_types.rsh +++ b/libs/rs/scriptc/rs_types.rsh @@ -1,98 +1,377 @@ +/* + * 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. + */ + +/** @file rs_types.rsh + * + * Define the standard Renderscript types + * + * Integers + * 8 bit: char, int8_t + * 16 bit: short, int16_t + * 32 bit: int, in32_t + * 64 bit: long, long long, int64_t + * + * Unsigned Integers + * 8 bit: uchar, uint8_t + * 16 bit: ushort, uint16_t + * 32 bit: uint, uint32_t + * 64 bit: ulong, uint64_t + * + * Floating point + * 32 bit: float + * 64 bit: double + * + * Vectors of length 2, 3, and 4 are supported for all the types above. + * + */ + #ifndef __RS_TYPES_RSH__ #define __RS_TYPES_RSH__ #define M_PI 3.14159265358979323846264338327950288f /* pi */ #include "stdbool.h" +/** + * 8 bit integer type + */ typedef char int8_t; +/** + * 16 bit integer type + */ typedef short int16_t; +/** + * 32 bit integer type + */ typedef int int32_t; +/** + * 64 bit integer type + */ typedef long long int64_t; - +/** + * 8 bit unsigned integer type + */ typedef unsigned char uint8_t; +/** + * 16 bit unsigned integer type + */ typedef unsigned short uint16_t; +/** + * 32 bit unsigned integer type + */ typedef unsigned int uint32_t; +/** + * 64 bit unsigned integer type + */ typedef unsigned long long uint64_t; - +/** + * 8 bit unsigned integer type + */ typedef uint8_t uchar; +/** + * 16 bit unsigned integer type + */ typedef uint16_t ushort; +/** + * 32 bit unsigned integer type + */ typedef uint32_t uint; +/** + * Typedef for unsigned char (use for 64-bit unsigned integers) + */ typedef uint64_t ulong; - +/** + * Typedef for unsigned int + */ typedef uint32_t size_t; +/** + * Typedef for int (use for 32-bit integers) + */ typedef int32_t ssize_t; +/** + * \brief Opaque handle to a RenderScript element. + * + * See: android.renderscript.Element + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_element; +/** + * \brief Opaque handle to a RenderScript type. + * + * See: android.renderscript.Type + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_type; +/** + * \brief Opaque handle to a RenderScript allocation. + * + * See: android.renderscript.Allocation + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_allocation; +/** + * \brief Opaque handle to a RenderScript sampler object. + * + * See: android.renderscript.Sampler + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_sampler; +/** + * \brief Opaque handle to a RenderScript script object. + * + * See: android.renderscript.ScriptC + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_script; +/** + * \brief Opaque handle to a RenderScript mesh object. + * + * See: android.renderscript.Mesh + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_mesh; +/** + * \brief Opaque handle to a RenderScript ProgramFragment object. + * + * See: android.renderscript.ProgramFragment + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_fragment; +/** + * \brief Opaque handle to a RenderScript ProgramVertex object. + * + * See: android.renderscript.ProgramVertex + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_vertex; +/** + * \brief Opaque handle to a RenderScript sampler object. + * + * See: android.renderscript.Sampler + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_raster; +/** + * \brief Opaque handle to a RenderScript ProgramStore object. + * + * See: android.renderscript.ProgramStore + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_program_store; +/** + * \brief Opaque handle to a RenderScript font object. + * + * See: android.renderscript.Font + */ typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_font; - +/** + * Vector version of the basic float type. + * Provides two float fields packed into a single 64bit field with 64 bit + * alignment. + */ typedef float float2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic float type. Provides three float fields packed + * into a single 128bit field with 128 bit alignment. + */ typedef float float3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic float type. + * Provides four float fields packed into a single 128bit field with 128bit + * alignment. + */ typedef float float4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic double type. Provides two double fields packed + * into a single 128bit field with 128bit alignment. + */ typedef double double2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic double type. Provides three double fields packed + * into a single 256bit field with 256bit alignment. + */ typedef double double3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic double type. Provides four double fields packed + * into a single 256bit field with 256bit alignment. + */ typedef double double4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic uchar type. Provides two uchar fields packed + * into a single 16bit field with 16bit alignment. + */ typedef uchar uchar2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic uchar type. Provides three uchar fields packed + * into a single 32bit field with 32bit alignment. + */ typedef uchar uchar3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic uchar type. Provides four uchar fields packed + * into a single 32bit field with 32bit alignment. + */ typedef uchar uchar4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic ushort type. Provides two ushort fields packed + * into a single 32bit field with 32bit alignment. + */ typedef ushort ushort2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic ushort type. Provides three ushort fields packed + * into a single 64bit field with 64bit alignment. + */ typedef ushort ushort3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic ushort type. Provides four ushort fields packed + * into a single 64bit field with 64bit alignment. + */ typedef ushort ushort4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic uint type. Provides two uint fields packed into a + * single 64bit field with 64bit alignment. + */ typedef uint uint2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic uint type. Provides three uint fields packed into + * a single 128bit field with 128bit alignment. + */ typedef uint uint3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic uint type. Provides four uint fields packed into + * a single 128bit field with 128bit alignment. + */ typedef uint uint4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic ulong type. Provides two ulong fields packed into + * a single 128bit field with 128bit alignment. + */ typedef ulong ulong2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic ulong type. Provides three ulong fields packed + * into a single 256bit field with 256bit alignment. + */ typedef ulong ulong3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic ulong type. Provides four ulong fields packed + * into a single 256bit field with 256bit alignment. + */ typedef ulong ulong4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic char type. Provides two char fields packed into a + * single 16bit field with 16bit alignment. + */ typedef char char2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic char type. Provides three char fields packed into + * a single 32bit field with 32bit alignment. + */ typedef char char3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic char type. Provides four char fields packed into + * a single 32bit field with 32bit alignment. + */ typedef char char4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic short type. Provides two short fields packed into + * a single 32bit field with 32bit alignment. + */ typedef short short2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic short type. Provides three short fields packed + * into a single 64bit field with 64bit alignment. + */ typedef short short3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic short type. Provides four short fields packed + * into a single 64bit field with 64bit alignment. + */ typedef short short4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic int type. Provides two int fields packed into a + * single 64bit field with 64bit alignment. + */ typedef int int2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic int type. Provides three int fields packed into a + * single 128bit field with 128bit alignment. + */ typedef int int3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic int type. Provides two four fields packed into a + * single 128bit field with 128bit alignment. + */ typedef int int4 __attribute__((ext_vector_type(4))); +/** + * Vector version of the basic long type. Provides two long fields packed into a + * single 128bit field with 128bit alignment. + */ typedef long long2 __attribute__((ext_vector_type(2))); +/** + * Vector version of the basic long type. Provides three long fields packed into + * a single 256bit field with 256bit alignment. + */ typedef long long3 __attribute__((ext_vector_type(3))); +/** + * Vector version of the basic long type. Provides four long fields packed into + * a single 256bit field with 256bit alignment. + */ typedef long long4 __attribute__((ext_vector_type(4))); +/** + * \brief 4x4 float matrix + * + * Native holder for RS matrix. Elements are stored in the array at the + * location [row*4 + col] + */ typedef struct { float m[16]; } rs_matrix4x4; - +/** + * \brief 3x3 float matrix + * + * Native holder for RS matrix. Elements are stored in the array at the + * location [row*3 + col] + */ typedef struct { float m[9]; } rs_matrix3x3; - +/** + * \brief 2x2 float matrix + * + * Native holder for RS matrix. Elements are stored in the array at the + * location [row*2 + col] + */ typedef struct { float m[4]; } rs_matrix2x2; +/** + * quaternion type for use with the quaternion functions + */ typedef float4 rs_quaternion; #define RS_PACKED __attribute__((packed, aligned(4))) - #define NULL ((const void *)0) + +/** + * \brief Enum for selecting cube map faces + * + * Used todo-alexst + */ typedef enum { RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X = 0, RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_X = 1, @@ -102,6 +381,12 @@ typedef enum { RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_Z = 5 } rs_allocation_cubemap_face; +/** + * \brief Bitfield to specify the usage types for an allocation. + * + * These values are ORed together to specify which usages or memory spaces are + * relevant to an allocation or an operation on an allocation. + */ typedef enum { RS_ALLOCATION_USAGE_SCRIPT = 0x0001, RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE = 0x0002, diff --git a/libs/ui/EGLUtils.cpp b/libs/ui/EGLUtils.cpp index 020646b9c416..f24a71d88d9d 100644 --- a/libs/ui/EGLUtils.cpp +++ b/libs/ui/EGLUtils.cpp @@ -24,8 +24,6 @@ #include <EGL/egl.h> -#include <system/graphics.h> - #include <private/ui/android_natives_priv.h> // ---------------------------------------------------------------------------- @@ -69,49 +67,31 @@ status_t EGLUtils::selectConfigForPixelFormat( return BAD_VALUE; // Get all the "potential match" configs... - if (eglChooseConfig(dpy, attrs, 0, 0, &numConfigs) == EGL_FALSE) + if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE) return BAD_VALUE; - if (numConfigs) { - EGLConfig* const configs = new EGLConfig[numConfigs]; - if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) { - delete [] configs; - return BAD_VALUE; - } - - bool hasAlpha = false; - switch (format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_BGRA_8888: - case HAL_PIXEL_FORMAT_RGBA_5551: - case HAL_PIXEL_FORMAT_RGBA_4444: - hasAlpha = true; - break; - } - - // The first config is guaranteed to over-satisfy the constraints - EGLConfig config = configs[0]; - - // go through the list and skip configs that over-satisfy our needs - int i; - for (i=0 ; i<n ; i++) { - if (!hasAlpha) { - EGLint alphaSize; - eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &alphaSize); - if (alphaSize > 0) { - continue; - } - } + EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs); + if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) { + free(configs); + return BAD_VALUE; + } + + int i; + EGLConfig config = NULL; + for (i=0 ; i<n ; i++) { + EGLint nativeVisualId = 0; + eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId); + if (nativeVisualId>0 && format == nativeVisualId) { config = configs[i]; break; } + } - delete [] configs; - - if (i<n) { - *outConfig = config; - return NO_ERROR; - } + free(configs); + + if (i<n) { + *outConfig = config; + return NO_ERROR; } return NAME_NOT_FOUND; diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 0e8ae619fc5c..89497302a25f 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -317,6 +317,8 @@ int FramebufferNativeWindow::perform(ANativeWindow* window, case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: case NATIVE_WINDOW_SET_BUFFERS_FORMAT: case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: + case NATIVE_WINDOW_API_CONNECT: + case NATIVE_WINDOW_API_DISCONNECT: // TODO: we should implement these return NO_ERROR; diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 33ef1fc8945c..e75415b37b0b 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -61,13 +61,19 @@ void GraphicBufferAllocator::dump(String8& result) const const size_t c = list.size(); for (size_t i=0 ; i<c ; i++) { const alloc_rec_t& rec(list.valueAt(i)); - snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n", - list.keyAt(i), rec.size/1024.0f, - rec.w, rec.s, rec.h, rec.format, rec.usage); + if (rec.size) { + snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n", + list.keyAt(i), rec.size/1024.0f, + rec.w, rec.s, rec.h, rec.format, rec.usage); + } else { + snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %8X | 0x%08x\n", + list.keyAt(i), + rec.w, rec.s, rec.h, rec.format, rec.usage); + } result.append(buffer); total += rec.size; } - snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f); + snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0f); result.append(buffer); if (mAllocDev->common.version >= 1 && mAllocDev->dump) { mAllocDev->dump(mAllocDev, buffer, SIZE); @@ -101,13 +107,19 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + int bpp = bytesPerPixel(format); + if (bpp < 0) { + // probably a HAL custom format. in any case, we don't know + // what its pixel size is. + bpp = 0; + } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; - rec.size = h * stride[0] * bytesPerPixel(format); + rec.size = h * stride[0] * bpp; list.add(*handle, rec); } diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp index 0af7f8043c35..688b99892bf9 100644 --- a/libs/ui/Input.cpp +++ b/libs/ui/Input.cpp @@ -280,6 +280,9 @@ status_t PointerCoords::setAxisValue(int32_t axis, float value) { uint64_t axisBit = 1LL << axis; uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); if (!(bits & axisBit)) { + if (value == 0) { + return OK; // axes with value 0 do not need to be stored + } uint32_t count = __builtin_popcountll(bits); if (count >= MAX_AXES) { tooManyAxes(axis); @@ -294,23 +297,10 @@ status_t PointerCoords::setAxisValue(int32_t axis, float value) { return OK; } -float* PointerCoords::editAxisValue(int32_t axis) { - if (axis < 0 || axis > 63) { - return NULL; - } - - uint64_t axisBit = 1LL << axis; - if (!(bits & axisBit)) { - return NULL; - } - uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); - return &values[index]; -} - static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { - float* value = c.editAxisValue(axis); - if (value) { - *value *= scaleFactor; + float value = c.getAxisValue(axis); + if (value != 0) { + c.setAxisValue(axis, value * scaleFactor); } } @@ -574,20 +564,14 @@ void MotionEvent::transform(const SkMatrix* matrix) { size_t numSamples = mSamplePointerCoords.size(); for (size_t i = 0; i < numSamples; i++) { PointerCoords& c = mSamplePointerCoords.editItemAt(i); - float* xPtr = c.editAxisValue(AMOTION_EVENT_AXIS_X); - float* yPtr = c.editAxisValue(AMOTION_EVENT_AXIS_Y); - if (xPtr && yPtr) { - float x = *xPtr + oldXOffset; - float y = *yPtr + oldYOffset; - matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), & point); - *xPtr = SkScalarToFloat(point.fX) - newXOffset; - *yPtr = SkScalarToFloat(point.fY) - newYOffset; - } + float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset; + float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset; + matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point); + c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset); + c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset); - float* orientationPtr = c.editAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); - if (orientationPtr) { - *orientationPtr = transformAngle(matrix, *orientationPtr); - } + float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); + c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation)); } } @@ -727,7 +711,7 @@ void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Posi } while (idBits.count() > MAX_POINTERS) { - idBits.clearBit(idBits.lastMarkedBit()); + idBits.clearLastMarkedBit(); } Movement& movement = mMovements[mIndex]; @@ -776,7 +760,7 @@ void VelocityTracker::addMovement(const MotionEvent* event) { // 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()); + downIdBits.markBit(event->getPointerId(event->getActionIndex())); clearPointers(downIdBits); break; } diff --git a/libs/ui/tests/InputEvent_test.cpp b/libs/ui/tests/InputEvent_test.cpp index e48d5b7dc53c..e21c464a1974 100644 --- a/libs/ui/tests/InputEvent_test.cpp +++ b/libs/ui/tests/InputEvent_test.cpp @@ -52,9 +52,6 @@ TEST_F(PointerCoordsTest, AxisValues) { ASSERT_EQ(0, coords.getAxisValue(1)) << "getAxisValue should return zero because axis is not present"; - ASSERT_EQ(NULL, coords.editAxisValue(0)) - << "editAxisValue should return null because axis is not present"; - // Set first axis. ASSERT_EQ(OK, coords.setAxisValue(1, 5)); ASSERT_EQ(0x00000002ULL, coords.bits); @@ -96,26 +93,17 @@ TEST_F(PointerCoordsTest, AxisValues) { ASSERT_EQ(2, coords.getAxisValue(3)) << "getAxisValue should return value of axis"; - // Edit an existing axis value in place. - valuePtr = coords.editAxisValue(1); - ASSERT_EQ(5, *valuePtr) - << "editAxisValue should return pointer to axis value"; - - *valuePtr = 7; - ASSERT_EQ(7, coords.getAxisValue(1)) - << "getAxisValue should return value of axis"; - // Set an axis with an id between the others. (inserting value in the middle) ASSERT_EQ(OK, coords.setAxisValue(2, 1)); ASSERT_EQ(0x0000000fULL, coords.bits); ASSERT_EQ(4, coords.values[0]); - ASSERT_EQ(7, coords.values[1]); + ASSERT_EQ(5, coords.values[1]); ASSERT_EQ(1, coords.values[2]); ASSERT_EQ(2, coords.values[3]); ASSERT_EQ(4, coords.getAxisValue(0)) << "getAxisValue should return value of axis"; - ASSERT_EQ(7, coords.getAxisValue(1)) + ASSERT_EQ(5, coords.getAxisValue(1)) << "getAxisValue should return value of axis"; ASSERT_EQ(1, coords.getAxisValue(2)) << "getAxisValue should return value of axis"; diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp index 8db2009587f7..37d061cb3cbb 100644 --- a/libs/utils/RefBase.cpp +++ b/libs/utils/RefBase.cpp @@ -49,11 +49,6 @@ namespace android { // --------------------------------------------------------------------------- -RefBase::Destroyer::~Destroyer() { -} - -// --------------------------------------------------------------------------- - class RefBase::weakref_impl : public RefBase::weakref_type { public: @@ -61,7 +56,6 @@ public: volatile int32_t mWeak; RefBase* const mBase; volatile int32_t mFlags; - Destroyer* mDestroyer; #if !DEBUG_REFS @@ -70,7 +64,6 @@ public: , mWeak(0) , mBase(base) , mFlags(0) - , mDestroyer(0) { } @@ -113,7 +106,7 @@ public: LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); #if DEBUG_REFS_CALLSTACK_ENABLED refs->stack.dump(); -#endif; +#endif refs = refs->next; } } @@ -131,7 +124,7 @@ public: LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); #if DEBUG_REFS_CALLSTACK_ENABLED refs->stack.dump(); -#endif; +#endif refs = refs->next; } } @@ -193,7 +186,7 @@ public: String8 text; { - Mutex::Autolock _l(const_cast<weakref_impl*>(this)->mMutex); + Mutex::Autolock _l(mMutex); char buf[128]; sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); text.append(buf); @@ -318,7 +311,7 @@ private: } } - Mutex mMutex; + mutable Mutex mMutex; ref_entry* mStrongRefs; ref_entry* mWeakRefs; @@ -348,7 +341,7 @@ void RefBase::incStrong(const void* id) const } android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); - const_cast<RefBase*>(this)->onFirstRef(); + refs->mBase->onFirstRef(); } void RefBase::decStrong(const void* id) const @@ -361,13 +354,9 @@ void RefBase::decStrong(const void* id) const #endif LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs); if (c == 1) { - const_cast<RefBase*>(this)->onLastStrongRef(id); - if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) { - if (refs->mDestroyer) { - refs->mDestroyer->destroy(this); - } else { - delete this; - } + refs->mBase->onLastStrongRef(id); + if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { + delete this; } } refs->decWeak(id); @@ -391,7 +380,7 @@ void RefBase::forceIncStrong(const void* id) const android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong); // fall through... case 0: - const_cast<RefBase*>(this)->onFirstRef(); + refs->mBase->onFirstRef(); } } @@ -400,10 +389,6 @@ int32_t RefBase::getStrongCount() const return mRefs->mStrong; } -void RefBase::setDestroyer(RefBase::Destroyer* destroyer) { - mRefs->mDestroyer = destroyer; -} - RefBase* RefBase::weakref_type::refBase() const { return static_cast<const weakref_impl*>(this)->mBase; @@ -417,6 +402,7 @@ void RefBase::weakref_type::incWeak(const void* id) LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this); } + void RefBase::weakref_type::decWeak(const void* id) { weakref_impl* const impl = static_cast<weakref_impl*>(this); @@ -424,30 +410,27 @@ void RefBase::weakref_type::decWeak(const void* id) const int32_t c = android_atomic_dec(&impl->mWeak); LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this); if (c != 1) return; - - if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) { + + if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) { + // This is the regular lifetime case. The object is destroyed + // when the last strong reference goes away. Since weakref_impl + // outlive the object, it is not destroyed in the dtor, and + // we'll have to do it here. if (impl->mStrong == INITIAL_STRONG_VALUE) { - if (impl->mBase) { - if (impl->mDestroyer) { - impl->mDestroyer->destroy(impl->mBase); - } else { - delete impl->mBase; - } - } + // Special case: we never had a strong reference, so we need to + // destroy the object now. + delete impl->mBase; } else { // LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase); delete impl; } } else { + // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER} impl->mBase->onLastWeakRef(id); - if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) { - if (impl->mBase) { - if (impl->mDestroyer) { - impl->mDestroyer->destroy(impl->mBase); - } else { - delete impl->mBase; - } - } + if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) { + // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference + // is gone, we can destroy the object. + delete impl->mBase; } } } @@ -569,11 +552,23 @@ RefBase::RefBase() RefBase::~RefBase() { - if ((mRefs->mFlags & OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK) { - if (mRefs->mWeak == 0) { - delete mRefs; + if (mRefs->mStrong == INITIAL_STRONG_VALUE) { + // we never acquired a strong (and/or weak) reference on this object. + delete mRefs; + } else { + // life-time of this object is extended to WEAK or FOREVER, in + // which case weakref_impl doesn't out-live the object and we + // can free it now. + if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) { + // It's possible that the weak count is not 0 if the object + // re-acquired a weak reference in its destructor + if (mRefs->mWeak == 0) { + delete mRefs; + } } } + // for debugging purposes, clear this. + const_cast<weakref_impl*&>(mRefs) = NULL; } void RefBase::extendObjectLifetime(int32_t mode) |