Skip to content

Commit

Permalink
Initial dirty region redraws for #287
Browse files Browse the repository at this point in the history
  • Loading branch information
koral-- committed Sep 11, 2016
1 parent 96f37dc commit bb482e6
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 20 deletions.
6 changes: 6 additions & 0 deletions src/main/java/pl/droidsonroids/gif/GifInfoHandle.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ static GifInfoHandle openUri(ContentResolver resolver, Uri uri, boolean justDeco

private static native void initTexImageDescriptor(long gifInfoPtr);

private static native void renderFrameGL(long gifInfoPtr, int target, int level);

synchronized long renderFrame(Bitmap frameBuffer) {
return renderFrame(gifInfoPtr, frameBuffer);
}
Expand Down Expand Up @@ -322,4 +324,8 @@ void seekToFrameGL(@IntRange(from = 0) final int index) {
}
seekToFrameGL(gifInfoPtr, index);
}

void renderFrameGL(int target, int level) {
renderFrameGL(gifInfoPtr, target, level);
}
}
4 changes: 4 additions & 0 deletions src/main/java/pl/droidsonroids/gif/GifTexImage2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ public int getHeight() {
return mGifInfoHandle.getHeight();
}

public void renderFrame(int target, int level) {
mGifInfoHandle.renderFrameGL(target, level);
}

@Override
protected final void finalize() throws Throwable {
try {
Expand Down
2 changes: 1 addition & 1 deletion src/main/jni/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_renderFrame(JNIEnv *env, jclass __unused
DDGifSlurp(info, true, false);
if (info->currentIndex == 0)
prepareCanvas(pixels, info);
const uint_fast32_t frameDuration = getBitmap(pixels, info);
const uint_fast32_t frameDuration = getBitmap(pixels, info, false);
unlockPixels(env, jbitmap);
return calculateInvalidationDelay(info, renderStartTime, frameDuration);
}
2 changes: 1 addition & 1 deletion src/main/jni/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ uint_fast32_t seek(GifInfo *info, uint_fast32_t desiredIndex, void *pixels) {

do {
DDGifSlurp(info, true, false);
drawNextBitmap(pixels, info);
drawNextBitmap(pixels, info, false);
} while (info->currentIndex++ < desiredIndex);
--info->currentIndex;
return getFrameDuration(info);
Expand Down
18 changes: 9 additions & 9 deletions src/main/jni/drawing.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extern void memset32_neon(uint32_t* dst, uint32_t value, int count);
#define MEMSET_ARGB(dst, value, count) memset(dst, value, count * sizeof(argb))
#endif

static inline void blitNormal(argb *bm, GifInfo *info, SavedImage *frame, ColorMapObject *cmap) {
static inline void blitNormal(argb *bm, GifInfo *info, SavedImage *frame, ColorMapObject *cmap, bool drawOnlyDirtyRegion) {
unsigned char *src = info->rasterBits;
argb *dst = GET_ADDR(bm, info->stride, frame->ImageDesc.Left, frame->ImageDesc.Top);

Expand Down Expand Up @@ -59,7 +59,7 @@ static inline void blitNormal(argb *bm, GifInfo *info, SavedImage *frame, ColorM
}
}

static void drawFrame(argb *bm, GifInfo *info, SavedImage *frame) {
static void drawFrame(argb *bm, GifInfo *info, SavedImage *frame, bool drawOnlyDirtyRegion) {
ColorMapObject *cmap;
if (frame->ImageDesc.ColorMap != NULL)
cmap = frame->ImageDesc.ColorMap;// use local color table
Expand All @@ -68,7 +68,7 @@ static void drawFrame(argb *bm, GifInfo *info, SavedImage *frame) {
else
cmap = getDefColorMap();

blitNormal(bm, info, frame, cmap);
blitNormal(bm, info, frame, cmap, drawOnlyDirtyRegion);
}

// return true if area of 'target' is completely covers area of 'covered'
Expand All @@ -81,7 +81,7 @@ static bool checkIfCover(const SavedImage *target, const SavedImage *covered) {
<= target->ImageDesc.Top + target->ImageDesc.Height;
}

static inline void disposeFrameIfNeeded(argb *bm, GifInfo *info) {
static inline void disposeFrameIfNeeded(argb *bm, GifInfo *info, bool drawOnlyDirtyRegion) {
GifFileType *fGif = info->gifFilePtr;
SavedImage *cur = &fGif->SavedImages[info->currentIndex - 1];
SavedImage *next = &fGif->SavedImages[info->currentIndex];
Expand Down Expand Up @@ -134,11 +134,11 @@ void prepareCanvas(const argb *bm, GifInfo *info) {
}
}

void drawNextBitmap(argb *bm, GifInfo *info) {
void drawNextBitmap(argb *bm, GifInfo *info, bool drawOnlyDirtyRegion) {
if (info->currentIndex > 0) {
disposeFrameIfNeeded(bm, info);
disposeFrameIfNeeded(bm, info, drawOnlyDirtyRegion);
}
drawFrame(bm, info, info->gifFilePtr->SavedImages + info->currentIndex);
drawFrame(bm, info, info->gifFilePtr->SavedImages + info->currentIndex, drawOnlyDirtyRegion);
}

uint_fast32_t getFrameDuration(GifInfo *info) {
Expand All @@ -159,7 +159,7 @@ uint_fast32_t getFrameDuration(GifInfo *info) {
return frameDuration;
}

uint_fast32_t getBitmap(argb *bm, GifInfo *info) {
drawNextBitmap(bm, info);
uint_fast32_t getBitmap(argb *bm, GifInfo *info, bool drawOnlyDirtyRegion) {
drawNextBitmap(bm, info, drawOnlyDirtyRegion);
return getFrameDuration(info);
}
10 changes: 5 additions & 5 deletions src/main/jni/gif.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,15 @@ void throwGifIOException(int errorCode, JNIEnv *env);

GifInfo *createGifHandle(GifSourceDescriptor *descriptor, JNIEnv *env, jboolean justDecodeMetaData);

static inline void blitNormal(argb *bm, GifInfo *info, SavedImage *frame, ColorMapObject *cmap);
static inline void blitNormal(argb *bm, GifInfo *info, SavedImage *frame, ColorMapObject *cmap, bool b);

static void drawFrame(argb *bm, GifInfo *info, SavedImage *frame);
static void drawFrame(argb *bm, GifInfo *info, SavedImage *frame, bool b);

static bool checkIfCover(const SavedImage *target, const SavedImage *covered);

static void disposeFrameIfNeeded(argb *bm, GifInfo *info);
static void disposeFrameIfNeeded(argb *bm, GifInfo *info, bool b);

uint_fast32_t getBitmap(argb *bm, GifInfo *info);
uint_fast32_t getBitmap(argb *bm, GifInfo *info, bool drawOnlyDirtyRegion);

bool reset(GifInfo *info);

Expand All @@ -209,7 +209,7 @@ jint restoreSavedState(GifInfo *info, JNIEnv *env, jlongArray state, void *pixel

void prepareCanvas(const argb *bm, GifInfo *info);

void drawNextBitmap(argb *bm, GifInfo *info);
void drawNextBitmap(argb *bm, GifInfo *info, bool drawOnlyDirtyRegion);

uint_fast32_t getFrameDuration(GifInfo *info);

Expand Down
2 changes: 1 addition & 1 deletion src/main/jni/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ jint restoreSavedState(GifInfo *info, JNIEnv *env, jlongArray state, void *pixel
prepareCanvas(pixels, info);
while (info->currentIndex < savedIndex) {
DDGifSlurp(info, true, false);
lastFrameDuration = getBitmap(pixels, info);
lastFrameDuration = getBitmap(pixels, info, false);
}
}

Expand Down
48 changes: 46 additions & 2 deletions src/main/jni/opengl.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ typedef struct {
void *frameBuffer;
pthread_mutex_t renderMutex;
pthread_t slurpThread;
//TODO bool cacheAnimation;
GLuint glFramebufferName;
GLuint *glTextureNames;
} TexImageDescriptor;

__unused JNIEXPORT void JNICALL
Expand Down Expand Up @@ -42,13 +45,14 @@ static void *slurp(void *pVoidInfo) {
GifInfo *info = pVoidInfo;
while (true) {
long renderStartTime = getRealTime();
//TODO only advance frame index if cacheAnimation is enabled and frame is cached
DDGifSlurp(info, true, false);
TexImageDescriptor *texImageDescriptor = info->frameBufferDescriptor;
pthread_mutex_lock(&texImageDescriptor->renderMutex);
if (info->currentIndex == 0) {
prepareCanvas(texImageDescriptor->frameBuffer, info);
}
const uint_fast32_t frameDuration = getBitmap(texImageDescriptor->frameBuffer, info);
const uint_fast32_t frameDuration = getBitmap(texImageDescriptor->frameBuffer, info, true);
pthread_mutex_unlock(&texImageDescriptor->renderMutex);

const long long invalidationDelayMillis = calculateInvalidationDelay(info, renderStartTime, frameDuration);
Expand Down Expand Up @@ -90,6 +94,7 @@ static void releaseTexImageDescriptor(GifInfo *info, JNIEnv *env) {
stopDecoderThread(env, descriptor);
info->frameBufferDescriptor = NULL;
free(descriptor->frameBuffer);
free(descriptor->glTextureNames);
errno = pthread_mutex_destroy(&descriptor->renderMutex);
THROW_ON_NONZERO_RESULT(errno, "Render mutex destroy failed ");
free(descriptor);
Expand All @@ -106,7 +111,6 @@ Java_pl_droidsonroids_gif_GifInfoHandle_initTexImageDescriptor(JNIEnv *env, jcla
throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE);
return;
}
descriptor->eventPollFd.fd = -1;
const GifWord width = info->gifFilePtr->SWidth;
const GifWord height = info->gifFilePtr->SHeight;
descriptor->frameBuffer = malloc(width * height * sizeof(argb));
Expand All @@ -115,7 +119,16 @@ Java_pl_droidsonroids_gif_GifInfoHandle_initTexImageDescriptor(JNIEnv *env, jcla
throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE);
return;
}
descriptor->glTextureNames = calloc(info->gifFilePtr->ImageCount, sizeof(GLuint));
if (descriptor->glTextureNames == NULL) {
free(descriptor->frameBuffer);
free(descriptor);
throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE);
return;
}
descriptor->glFramebufferName = 0;
info->stride = (int32_t) width;
descriptor->eventPollFd.fd = -1;
info->frameBufferDescriptor = descriptor;
errno = pthread_mutex_init(&descriptor->renderMutex, NULL);
THROW_ON_NONZERO_RESULT(errno, "Render mutex initialization failed ");
Expand Down Expand Up @@ -165,3 +178,34 @@ Java_pl_droidsonroids_gif_GifInfoHandle_seekToFrameGL(__unused JNIEnv *env, jcla
seek(info, (uint_fast32_t) desiredIndex, descriptor->frameBuffer);
}

__unused JNIEXPORT void JNICALL
Java_pl_droidsonroids_gif_GifInfoHandle_renderFrameGL(JNIEnv *__unused env, jclass __unused handleClass, jlong gifInfo, jint rawTarget, jint level) {
GifInfo *info = (GifInfo *) (intptr_t) gifInfo;
if (info == NULL) {
return;
}
TexImageDescriptor *descriptor = info->frameBufferDescriptor;
pthread_mutex_lock(&descriptor->renderMutex);
GLuint *currentTextureName = descriptor->glTextureNames + info->currentIndex;
if (*currentTextureName != 0) {
glBindTexture(GL_TEXTURE_2D, *currentTextureName);
} else {
GLuint *framebufferName = &descriptor->glFramebufferName;
if (*framebufferName == 0) {
glGenFramebuffers(1, framebufferName); //TODO delete
}
glGenTextures(1, currentTextureName);//TODO delete
const GLsizei width = (const GLsizei) info->gifFilePtr->SWidth;
const GLsizei height = (const GLsizei) info->gifFilePtr->SHeight;
const GLenum target = (const GLenum) rawTarget;
glBindTexture(target, *currentTextureName);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, descriptor->frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, *framebufferName);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, *currentTextureName, level);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
pthread_mutex_unlock(&descriptor->renderMutex);
}
2 changes: 1 addition & 1 deletion src/main/jni/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_bindSurface(JNIEnv *env, jclass __unused
descriptor->renderHelper = 0;
pthread_mutex_unlock(&descriptor->renderMutex);

const uint_fast32_t frameDuration = getBitmap(buffer.bits, info);
const uint_fast32_t frameDuration = getBitmap(buffer.bits, info, false);

pthread_mutex_lock(&descriptor->slurpMutex);
descriptor->slurpHelper = 1;
Expand Down

0 comments on commit bb482e6

Please sign in to comment.