static void ditherRow(struct pam * const inpamP, const tuple * const inrow, const scaler * const scalerP, unsigned int ** const ditherMatrix, unsigned int const ditherMatrixArea, struct colorResolution const colorRes, unsigned int const row, unsigned int const modMask, struct pam * const outpamP, tuple * const outrow) { unsigned int col; for (col = 0; col < inpamP->width; ++col) { unsigned int const d = ditherMatrix[row & modMask][(inpamP->width-col-1) & modMask]; unsigned int dithered[3]; unsigned int plane; assert(inpamP->depth >= 3); for (plane = 0; plane < 3; ++plane) dithered[plane] = dither(inrow[col][plane], inpamP->maxval, d, colorRes.c[plane]-1, ditherMatrixArea); pnm_assigntuple(outpamP, outrow[col], scaler_scale(scalerP, dithered[PAM_RED_PLANE], dithered[PAM_GRN_PLANE], dithered[PAM_BLU_PLANE])); } }
SDL_Texture* tcache_get(surface *sur, screen_palette *pal, char *remap_table, uint8_t pal_offset) { if(sur == NULL || sur->w == 0 || sur->h == 0 || sur->data == NULL) { if(sur != NULL) { DEBUG("Invalid surface requested from tcache: w,h = %d,%d data = %p", sur->w, sur->h, sur->data); } else { DEBUG("Invalid surface requested from tcache: w,h = %d,%d surface = %p", sur->w, sur->h, sur); } return NULL; } // Form a key tcache_entry_key key; memset(&key, 0, sizeof(tcache_entry_key)); key.c_pal_offset = (sur->type == SURFACE_TYPE_RGBA) ? 0 : pal_offset; key.c_remap_table = (sur->type == SURFACE_TYPE_RGBA) ? 0 : remap_table; key.c_surface = sur; key.w = sur->w; key.h = sur->h; // Attempt to find appropriate surface // If surface is cacheable and hasn't changed, just return here. tcache_entry_value *val = tcache_get_entry(&key); if(val != NULL && (val->pal_version == pal->version || sur->type == SURFACE_TYPE_RGBA) && !sur->force_refresh) { val->age = 0; cache->hits++; return val->tex; } // Reset refresh flag here sur->force_refresh = 0; // If there was no fitting surface tex in the cache at all, // then we need to create one if(val == NULL) { tcache_entry_value new_entry; new_entry.age = 0; new_entry.pal_version = pal->version; new_entry.tex = SDL_CreateTexture(cache->renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, sur->w * cache->scale_factor, sur->h * cache->scale_factor); SDL_SetTextureBlendMode(new_entry.tex, SDL_BLENDMODE_BLEND); val = tcache_add_entry(&key, &new_entry); } // We have a texture either from the cache, or we just created one. // Either one, it needs to be updated. Let's do it now. // Also, scale surface if necessary if(cache->scale_factor > 1) { char *raw = malloc(sur->w * sur->h * 4); surface scaled; surface_create(&scaled, SURFACE_TYPE_RGBA, sur->w * cache->scale_factor, sur->h * cache->scale_factor); surface_to_rgba(sur, raw, pal, remap_table, pal_offset); scaler_scale(cache->scaler, raw, scaled.data, sur->w, sur->h, cache->scale_factor); surface_to_texture(&scaled, val->tex, pal, remap_table, pal_offset); surface_free(&scaled); free(raw); } else { surface_to_texture(sur, val->tex, pal, remap_table, pal_offset); } // Set correct age and palette version val->age = 0; val->pal_version = pal->version; // Do some statistics stuff cache->misses++; return val->tex; }