@@ -122,6 +122,8 @@ static void poolInit(IOSurfacePool *pool) {
122122 pool->count = 0 ;
123123 pool->back = 0 ;
124124 pool->front = 0 ;
125+ memset (&pool->stats , 0 , sizeof (pool->stats ));
126+ pool->lastLogTime = CFAbsoluteTimeGetCurrent ();
125127}
126128
127129static void poolDestroy (IOSurfacePool *pool) {
@@ -212,6 +214,7 @@ static int poolNextBack(IOSurfacePool *pool, CALayer *layer) {
212214 for (int i = 0 ; i < pool->count ; i++) {
213215 if (i == pool->front ) continue ;
214216 if (poolSurfaceMatchesSize (pool, i, layer) && !IOSurfaceIsInUse (pool->entries [i].surface )) {
217+ pool->stats .reuses ++;
215218 return i;
216219 }
217220 }
@@ -220,23 +223,53 @@ static int poolNextBack(IOSurfacePool *pool, CALayer *layer) {
220223 for (int i = 0 ; i < pool->count ; i++) {
221224 if (i == pool->front ) continue ;
222225 if (pool->entries [i].surface && !IOSurfaceIsInUse (pool->entries [i].surface )) {
226+ pool->stats .recycles ++;
223227 return i;
224228 }
225229 }
226230
227231 // Grow pool if nothing was available
228232 if (pool->count < RLAWT_MAX_POOL) {
229- return pool->count ++;
233+ int idx = pool->count ++;
234+ pool->stats .grows ++;
235+ if (pool->count > pool->stats .highWater ) {
236+ pool->stats .highWater = pool->count ;
237+ }
238+ return idx;
230239 }
231240
232241 // Pool full, all in use -- evict first non-front entry.
233242 // count >= 2 is guaranteed here (pool grows on first swap), so this always finds one.
234243 for (int i = 0 ; i < pool->count ; i++) {
235- if (i != pool->front ) return i;
244+ if (i != pool->front ) {
245+ pool->stats .evictions ++;
246+ return i;
247+ }
236248 }
237249 return 0 ; // unreachable
238250}
239251
252+ static void poolLogStats (IOSurfacePool *pool) {
253+ CFAbsoluteTime now = CFAbsoluteTimeGetCurrent ();
254+ if (now - pool->lastLogTime < 60.0 ) return ;
255+
256+ NSLog (@" IOSurfacePool: %d swaps, %d allocs, pool %d /%d (hw %d ), %d reuse, %d recycle, %d grow, %d evict, %d fail" ,
257+ pool->stats .swaps ,
258+ pool->stats .allocs ,
259+ pool->count ,
260+ RLAWT_MAX_POOL,
261+ pool->stats .highWater ,
262+ pool->stats .reuses ,
263+ pool->stats .recycles ,
264+ pool->stats .grows ,
265+ pool->stats .evictions ,
266+ pool->stats .failures );
267+
268+ memset (&pool->stats , 0 , sizeof (pool->stats ));
269+ pool->stats .highWater = pool->count ;
270+ pool->lastLogTime = now;
271+ }
272+
240273JNIEXPORT void JNICALL Java_net_runelite_rlawt_AWTContext_createGLContext (JNIEnv *env, jobject self) {
241274 AWTContext *ctx = rlawtGetContext (env, self);
242275 if (!ctx || !rlawtContextState (env, ctx, false )) {
@@ -378,16 +411,22 @@ JNIEXPORT void JNICALL Java_net_runelite_rlawt_AWTContext_swapBuffers(JNIEnv *en
378411 withObject: (id )(pool->entries[pool->front].surface)
379412 waitUntilDone: true ];
380413
414+ pool->stats .swaps ++;
415+
381416 // Find a free surface for the next frame
382417 pool->back = poolNextBack (pool, ctx->layer );
383418
384419 // Create/recreate surface if needed (new slot, wrong size, or still held by compositor)
385420 if (!poolSurfaceMatchesSize (pool, pool->back , ctx->layer )
386421 || IOSurfaceIsInUse (pool->entries [pool->back].surface )) {
387422 if (!poolCreateSurface (env, pool, pool->back , ctx->layer , ctx->context )) {
423+ pool->stats .failures ++;
388424 return ;
389425 }
426+ pool->stats .allocs ++;
390427 }
428+
429+ poolLogStats (pool);
391430}
392431
393432JNIEXPORT jint JNICALL Java_net_runelite_rlawt_AWTContext_getFramebuffer (JNIEnv *env, jobject self, jboolean front) {
0 commit comments