Skip to content

Commit

Permalink
Merge branch 'main' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnylqm authored Nov 12, 2023
2 parents 552e7bf + ac7d9c4 commit dfa54cf
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,20 @@

package com.facebook.fresco.animation.bitmap.preparation.loadframe

import java.util.concurrent.PriorityBlockingQueue
import java.util.concurrent.Executors
import java.util.concurrent.ThreadFactory
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit

/**
* This executor allocated a high priority pool of thread. The priority is high because the task
* affect directly to the UI render frame. In order to avoid glitches or bad UX, this tasks should
* be finished asap
*/
object AnimationLoaderExecutor {
private val THREADS = Runtime.getRuntime().availableProcessors() * 2

private val uiThreadFactory = ThreadFactory { runnable: Runnable? ->
private val frameThreadFactory = ThreadFactory { runnable: Runnable? ->
val thread = Thread(runnable)
thread.priority = Thread.MAX_PRIORITY - 1
thread.priority = Thread.MIN_PRIORITY
thread
}

private val executor: ThreadPoolExecutor =
ThreadPoolExecutor(
THREADS, THREADS, 0L, TimeUnit.MILLISECONDS, PriorityBlockingQueue(), uiThreadFactory)
private val executor = Executors.newCachedThreadPool(frameThreadFactory)

fun execute(task: LoadFramePriorityTask) {
fun execute(task: Runnable) {
executor.execute(task)
}
}

interface LoadFramePriorityTask : Comparable<LoadFramePriorityTask>, Runnable {
val priority: Priority

override fun compareTo(other: LoadFramePriorityTask): Int {
return other.priority.compareTo(priority)
}

enum class Priority(val value: Int) {
HIGH(Thread.MAX_PRIORITY),
MEDIUM(Thread.NORM_PRIORITY),
LOW(Thread.MIN_PRIORITY)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,11 @@ import com.facebook.fresco.animation.backend.AnimationInformation
import com.facebook.fresco.animation.bitmap.BitmapFrameRenderer
import com.facebook.fresco.animation.bitmap.preparation.loadframe.AnimationLoaderExecutor
import com.facebook.fresco.animation.bitmap.preparation.loadframe.FpsCompressorInfo
import com.facebook.fresco.animation.bitmap.preparation.loadframe.LoadFramePriorityTask
import com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory
import java.util.ArrayDeque
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit
import kotlin.collections.Map
import kotlin.collections.Set
import kotlin.collections.emptyMap
import kotlin.collections.emptySet
import kotlin.collections.filter
import kotlin.collections.filterNotNull
import kotlin.collections.firstNotNullOfOrNull
import kotlin.collections.forEach
import kotlin.collections.minus
import kotlin.collections.set
import kotlin.collections.toSet

/**
* This frame loader uses a fixed number of bitmap. The buffer loads the next bunch of frames when
Expand Down Expand Up @@ -113,17 +102,6 @@ class BufferFrameLoader(
renderableFrameIndexes = compressionFrameMap.values.toSet()
}

/** Left only the last rendered bitmap on the buffer */
override fun onStop() {
val nearestFrame = findNearestFrame(lastRenderedFrameNumber)

val indexesToClose = bufferFramesHash.keys.minus(nearestFrame?.frameNumber).filterNotNull()
indexesToClose.forEach { frameNumber ->
bufferFramesHash[frameNumber]?.release()
bufferFramesHash.remove(frameNumber)
}
}

/** Release all bitmaps */
override fun clear() {
bufferFramesHash.values.forEach { it.release() }
Expand All @@ -137,18 +115,13 @@ class BufferFrameLoader(
}
isFetching = true

AnimationLoaderExecutor.execute(
object : LoadFramePriorityTask {
override val priority = LoadFramePriorityTask.Priority.HIGH

override fun run() {
do {
val targetFrame = lastRenderedFrameNumber.coerceAtLeast(0)
val success = extractDemandedFrame(targetFrame, width, height)
} while (!success)
isFetching = false
}
})
AnimationLoaderExecutor.execute {
do {
val targetFrame = lastRenderedFrameNumber.coerceAtLeast(0)
val success = extractDemandedFrame(targetFrame, width, height)
} while (!success)
isFetching = false
}
}

@WorkerThread
Expand Down Expand Up @@ -177,11 +150,10 @@ class BufferFrameLoader(

val deprecatedFrameNumber = oldFramesNumbers.pollFirst() ?: -1
val cachedFrame = bufferFramesHash[deprecatedFrameNumber]

var bufferFrame: BufferFrame
var bitmapRef: CloseableReference<Bitmap>

val bufferFrame: BufferFrame
val bitmapRef: CloseableReference<Bitmap>
val ref = cachedFrame?.bitmapRef?.cloneOrNull()

if (ref != null) {
bufferFrame = cachedFrame
bitmapRef = ref
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.fresco.ui.common

class SimpleImagePerfNotifier(private val imagePerfDataListener: ImagePerfDataListener) :
ImagePerfNotifier {

override fun notifyListenersOfVisibilityStateUpdate(
state: ImagePerfState,
visibilityState: VisibilityState
) {
imagePerfDataListener.onImageVisibilityUpdated(state.snapshot(), visibilityState)
}

override fun notifyStatusUpdated(state: ImagePerfState, imageLoadStatus: ImageLoadStatus) {
imagePerfDataListener.onImageLoadStatusUpdated(state.snapshot(), imageLoadStatus)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import com.facebook.drawee.components.DeferredReleaser
object ImageReleaseScheduler {
private const val RELEASE_DELAY: Long = 16 * 5 // Roughly 5 frames.

var improveDelayedReleasing = false

class ImageReleaseState(val drawable: KFrescoVitoDrawable) :
Runnable, DeferredReleaser.Releasable {

Expand Down Expand Up @@ -44,6 +46,9 @@ object ImageReleaseScheduler {
}
drawable.imagePerfListener.onScheduleReleaseDelayed(drawable)
handler.postDelayed(drawable.releaseState, RELEASE_DELAY)
if (improveDelayedReleasing) {
drawable.releaseState.delayedReleasePending = true
}
}

fun releaseNextFrame(drawable: KFrescoVitoDrawable) {
Expand All @@ -58,7 +63,9 @@ object ImageReleaseScheduler {
}

fun cancelReleaseDelayed(drawable: KFrescoVitoDrawable) {
handler.removeCallbacks(drawable.releaseState)
if (!improveDelayedReleasing || drawable.releaseState.delayedReleasePending) {
handler.removeCallbacks(drawable.releaseState)
}
drawable.releaseState.delayedReleasePending = false
}

Expand Down

0 comments on commit dfa54cf

Please sign in to comment.