this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Added GPU_ReplaceImage() for replacing the underlying texture of the given image. This makes it possible to change an image's size.

+496 -16
+3
include/SDL_gpu.h
··· 1007 1007 /*! Update an image from an array of pixel data. Ignores virtual resolution on the image so the number of pixels needed from the surface is known. */ 1008 1008 DECLSPEC void SDLCALL GPU_UpdateImageBytes(GPU_Image* image, const GPU_Rect* image_rect, const unsigned char* bytes, int bytes_per_row); 1009 1009 1010 + /*! Update an image from surface data, replacing its underlying texture to allow for size changes. Ignores virtual resolution on the image so the number of pixels needed from the surface is known. */ 1011 + DECLSPEC Uint8 SDLCALL GPU_ReplaceImage(GPU_Image* image, SDL_Surface* surface, const GPU_Rect* surface_rect); 1012 + 1010 1013 /*! Save image to a file. 1011 1014 * With a format of GPU_FILE_AUTO, the file type is deduced from the extension. Supported formats are: png, bmp, tga. 1012 1015 * Returns 0 on failure. */
+3
include/SDL_gpu_RendererImpl.h
··· 79 79 /*! \see GPU_UpdateImageBytes */ 80 80 void (SDLCALL *UpdateImageBytes)(GPU_Renderer* renderer, GPU_Image* image, const GPU_Rect* image_rect, const unsigned char* bytes, int bytes_per_row); 81 81 82 + /*! \see GPU_ReplaceImage */ 83 + Uint8 (SDLCALL *ReplaceImage)(GPU_Renderer* renderer, GPU_Image* image, SDL_Surface* surface, const GPU_Rect* surface_rect); 84 + 82 85 /*! \see GPU_CopyImageFromSurface() */ 83 86 GPU_Image* (SDLCALL *CopyImageFromSurface)(GPU_Renderer* renderer, SDL_Surface* surface); 84 87
+8
src/SDL_gpu.c
··· 934 934 _gpu_current_renderer->impl->UpdateImageBytes(_gpu_current_renderer, image, image_rect, bytes, bytes_per_row); 935 935 } 936 936 937 + Uint8 GPU_ReplaceImage(GPU_Image* image, SDL_Surface* surface, const GPU_Rect* surface_rect) 938 + { 939 + if(_gpu_current_renderer == NULL || _gpu_current_renderer->current_context_target == NULL) 940 + return 0; 941 + 942 + return _gpu_current_renderer->impl->ReplaceImage(_gpu_current_renderer, image, surface, surface_rect); 943 + } 944 + 937 945 SDL_Surface* GPU_LoadSurface(const char* filename) 938 946 { 939 947 int width, height, channels;
+227 -16
src/renderer_GL_common.inl
··· 1789 1789 return old_camera; 1790 1790 } 1791 1791 1792 + static GLuint CreateUninitializedTexture(GPU_Renderer* renderer) 1793 + { 1794 + GLuint handle; 1795 + 1796 + glGenTextures(1, &handle); 1797 + if(handle == 0) 1798 + return 0; 1799 + 1800 + flushAndBindTexture(renderer, handle); 1801 + 1802 + // Set the texture's stretching properties 1803 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1804 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1805 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1806 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1807 + #if defined(SDL_GPU_USE_GLES) && (SDL_GPU_GLES_TIER == 1) 1808 + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 1809 + 1810 + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); 1811 + #endif 1812 + 1813 + return handle; 1814 + } 1792 1815 1793 1816 static GPU_Image* CreateUninitializedImage(GPU_Renderer* renderer, Uint16 w, Uint16 h, GPU_FormatEnum format) 1794 1817 { ··· 1852 1875 GPU_PushErrorCode("GPU_CreateUninitializedImage", GPU_ERROR_DATA_ERROR, "Unsupported number of bytes per pixel (%d)", bytes_per_pixel); 1853 1876 return NULL; 1854 1877 } 1855 - 1856 - glGenTextures( 1, &handle ); 1878 + 1879 + // Create the underlying texture 1880 + handle = CreateUninitializedTexture(renderer); 1857 1881 if(handle == 0) 1858 1882 { 1859 1883 GPU_PushErrorCode("GPU_CreateUninitializedImage", GPU_ERROR_BACKEND_ERROR, "Failed to generate a texture handle."); 1860 1884 return NULL; 1861 1885 } 1862 - 1863 - flushAndBindTexture( renderer, handle ); 1864 - 1865 - // Set the texture's stretching properties 1866 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 1867 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 1868 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); 1869 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); 1870 - #if defined(SDL_GPU_USE_GLES) && (SDL_GPU_GLES_TIER == 1) 1871 - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 1872 - 1873 - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); 1874 - #endif 1875 - 1886 + 1887 + // Create the GPU_Image 1876 1888 result = (GPU_Image*)SDL_malloc(sizeof(GPU_Image)); 1877 1889 result->refcount = 1; 1878 1890 data = (GPU_IMAGE_DATA*)SDL_malloc(sizeof(GPU_IMAGE_DATA)); ··· 3169 3181 } 3170 3182 3171 3183 3184 + 3185 + static Uint8 ReplaceImage(GPU_Renderer* renderer, GPU_Image* image, SDL_Surface* surface, const GPU_Rect* surface_rect) 3186 + { 3187 + GPU_IMAGE_DATA* data; 3188 + GPU_Rect sourceRect; 3189 + SDL_Surface* newSurface; 3190 + GLenum internal_format; 3191 + Uint8* pixels; 3192 + int w, h; 3193 + int alignment; 3194 + 3195 + if(image == NULL) 3196 + { 3197 + GPU_PushErrorCode("GPU_ReplaceImage", GPU_ERROR_NULL_ARGUMENT, "image"); 3198 + return 0; 3199 + } 3200 + 3201 + if(surface == NULL) 3202 + { 3203 + GPU_PushErrorCode("GPU_ReplaceImage", GPU_ERROR_NULL_ARGUMENT, "surface"); 3204 + return 0; 3205 + } 3206 + 3207 + data = (GPU_IMAGE_DATA*)image->data; 3208 + internal_format = data->format; 3209 + 3210 + newSurface = copySurfaceIfNeeded(renderer, internal_format, surface, &internal_format); 3211 + if(newSurface == NULL) 3212 + { 3213 + GPU_PushErrorCode("GPU_ReplaceImage", GPU_ERROR_BACKEND_ERROR, "Failed to convert surface to proper pixel format."); 3214 + return 0; 3215 + } 3216 + 3217 + // Free the attached framebuffer 3218 + if((renderer->enabled_features & GPU_FEATURE_RENDER_TARGETS) && image->target != NULL) 3219 + { 3220 + GPU_TARGET_DATA* tdata = (GPU_TARGET_DATA*)image->target->data; 3221 + if(renderer->current_context_target != NULL) 3222 + flushAndClearBlitBufferIfCurrentFramebuffer(renderer, image->target); 3223 + if(tdata->handle != 0) 3224 + glDeleteFramebuffers(1, &tdata->handle); 3225 + tdata->handle = 0; 3226 + } 3227 + 3228 + // Free the old texture 3229 + if(data->owns_handle) 3230 + glDeleteTextures( 1, &data->handle); 3231 + data->handle = 0; 3232 + 3233 + // Get the area of the surface we'll use 3234 + if(surface_rect == NULL) 3235 + { 3236 + sourceRect.x = 0; 3237 + sourceRect.y = 0; 3238 + sourceRect.w = surface->w; 3239 + sourceRect.h = surface->h; 3240 + } 3241 + else 3242 + sourceRect = *surface_rect; 3243 + 3244 + // Clip the source rect to the surface 3245 + if(sourceRect.x < 0) 3246 + { 3247 + sourceRect.w += sourceRect.x; 3248 + sourceRect.x = 0; 3249 + } 3250 + if(sourceRect.y < 0) 3251 + { 3252 + sourceRect.h += sourceRect.y; 3253 + sourceRect.y = 0; 3254 + } 3255 + if(sourceRect.x >= surface->w) 3256 + sourceRect.x = surface->w - 1; 3257 + if(sourceRect.y >= surface->h) 3258 + sourceRect.y = surface->h - 1; 3259 + 3260 + if(sourceRect.x + sourceRect.w > surface->w) 3261 + sourceRect.w = surface->w - sourceRect.x; 3262 + if(sourceRect.y + sourceRect.h > surface->h) 3263 + sourceRect.h = surface->h - sourceRect.y; 3264 + 3265 + if(sourceRect.w <= 0 || sourceRect.h <= 0) 3266 + { 3267 + GPU_PushErrorCode("GPU_ReplaceImage", GPU_ERROR_DATA_ERROR, "Clipped source rect has zero size."); 3268 + return 0; 3269 + } 3270 + 3271 + // Allocate new texture 3272 + data->handle = CreateUninitializedTexture(renderer); 3273 + data->owns_handle = 1; 3274 + if(data->handle == 0) 3275 + { 3276 + GPU_PushErrorCode("GPU_ReplaceImage", GPU_ERROR_BACKEND_ERROR, "Failed to create a new texture handle."); 3277 + return 0; 3278 + } 3279 + 3280 + // Update image members 3281 + w = sourceRect.w; 3282 + h = sourceRect.h; 3283 + 3284 + if(!image->using_virtual_resolution) 3285 + { 3286 + image->w = w; 3287 + image->h = h; 3288 + } 3289 + image->base_w = w; 3290 + image->base_h = h; 3291 + 3292 + if(!(renderer->enabled_features & GPU_FEATURE_NON_POWER_OF_TWO)) 3293 + { 3294 + if(!isPowerOfTwo(w)) 3295 + w = getNearestPowerOf2(w); 3296 + if(!isPowerOfTwo(h)) 3297 + h = getNearestPowerOf2(h); 3298 + } 3299 + image->texture_w = w; 3300 + image->texture_h = h; 3301 + 3302 + image->has_mipmaps = 0; 3303 + 3304 + 3305 + // Upload surface pixel data 3306 + alignment = 1; 3307 + if(newSurface->format->BytesPerPixel == 4) 3308 + alignment = 4; 3309 + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); 3310 + #ifdef SDL_GPU_USE_OPENGL 3311 + glPixelStorei(GL_UNPACK_ROW_LENGTH, (newSurface->pitch / newSurface->format->BytesPerPixel)); 3312 + #endif 3313 + 3314 + pixels = (Uint8*)newSurface->pixels; 3315 + // Shift the pixels pointer to the proper source position 3316 + pixels += (int)(newSurface->pitch * sourceRect.y + (newSurface->format->BytesPerPixel)*sourceRect.x); 3317 + 3318 + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, 3319 + internal_format, GL_UNSIGNED_BYTE, pixels); 3320 + 3321 + // Delete temporary surface 3322 + if(surface != newSurface) 3323 + SDL_FreeSurface(newSurface); 3324 + 3325 + // Restore GL defaults 3326 + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 3327 + #ifdef SDL_GPU_USE_OPENGL 3328 + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 3329 + #endif 3330 + 3331 + 3332 + 3333 + // Update target members 3334 + if((renderer->enabled_features & GPU_FEATURE_RENDER_TARGETS) && image->target != NULL) 3335 + { 3336 + GLenum status; 3337 + GPU_Target* target = image->target; 3338 + GPU_TARGET_DATA* tdata = (GPU_TARGET_DATA*)target->data; 3339 + 3340 + // Create framebuffer object 3341 + glGenFramebuffers(1, &tdata->handle); 3342 + if(tdata->handle == 0) 3343 + { 3344 + GPU_PushErrorCode("GPU_ReplaceImage", GPU_ERROR_BACKEND_ERROR, "Failed to create new framebuffer target."); 3345 + return 0; 3346 + } 3347 + 3348 + flushAndBindFramebuffer(renderer, tdata->handle); 3349 + 3350 + // Attach the texture to it 3351 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, data->handle, 0); 3352 + 3353 + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 3354 + if(status != GL_FRAMEBUFFER_COMPLETE) 3355 + { 3356 + GPU_PushErrorCode("GPU_ReplaceImage", GPU_ERROR_BACKEND_ERROR, "Failed to recreate framebuffer target."); 3357 + return 0; 3358 + } 3359 + 3360 + if(!target->using_virtual_resolution) 3361 + { 3362 + target->w = image->base_w; 3363 + target->h = image->base_h; 3364 + } 3365 + target->base_w = image->texture_w; 3366 + target->base_h = image->texture_h; 3367 + 3368 + // Reset viewport? 3369 + target->viewport = GPU_MakeRect(0, 0, target->w, target->h); 3370 + } 3371 + 3372 + return 1; 3373 + } 3374 + 3375 + 3172 3376 static_inline Uint32 getPixel(SDL_Surface *Surface, int x, int y) 3173 3377 { 3174 3378 Uint8* bits; ··· 3214 3418 if(surface == NULL) 3215 3419 { 3216 3420 GPU_PushErrorCode("GPU_CopyImageFromSurface", GPU_ERROR_NULL_ARGUMENT, "surface"); 3421 + return NULL; 3422 + } 3423 + 3424 + if(surface->w == 0 || surface->h == 0) 3425 + { 3426 + GPU_PushErrorCode("GPU_CopyImageFromSurface", GPU_ERROR_DATA_ERROR, "Surface has a zero dimension."); 3217 3427 return NULL; 3218 3428 } 3219 3429 ··· 6139 6349 impl->CopyImage = &CopyImage; \ 6140 6350 impl->UpdateImage = &UpdateImage; \ 6141 6351 impl->UpdateImageBytes = &UpdateImageBytes; \ 6352 + impl->ReplaceImage = &ReplaceImage; \ 6142 6353 impl->CopyImageFromSurface = &CopyImageFromSurface; \ 6143 6354 impl->CopyImageFromTarget = &CopyImageFromTarget; \ 6144 6355 impl->CopySurfaceFromTarget = &CopySurfaceFromTarget; \
+3
tests/CMakeLists.txt
··· 114 114 add_executable(coordinate-mode-test coordinate-mode/main.c) 115 115 target_link_libraries (coordinate-mode-test ${TEST_LIBS}) 116 116 117 + add_executable(replace-image-test replace-image/main.c) 118 + target_link_libraries (replace-image-test ${TEST_LIBS}) 119 + 117 120 add_executable(sandbox-test sandbox/main.c) 118 121 target_link_libraries (sandbox-test ${TEST_LIBS}) 119 122
+6
tests/renderer/main.c
··· 537 537 GPU_Log(" %s (dummy)\n", __func__); 538 538 } 539 539 540 + static Uint8 ReplaceImage(GPU_Renderer* renderer, GPU_Image* image, SDL_Surface* surface, const GPU_Rect* surface_rect) 541 + { 542 + GPU_Log(" %s (dummy)\n", __func__); 543 + return 0; 544 + } 540 545 541 546 static GPU_Image* CopyImageFromSurface(GPU_Renderer* renderer, SDL_Surface* surface) 542 547 { ··· 1198 1203 impl->CopyImage = &CopyImage; 1199 1204 impl->UpdateImage = &UpdateImage; 1200 1205 impl->UpdateImageBytes = &UpdateImageBytes; 1206 + impl->ReplaceImage = &ReplaceImage; 1201 1207 impl->CopyImageFromSurface = &CopyImageFromSurface; 1202 1208 impl->CopyImageFromTarget = &CopyImageFromTarget; 1203 1209 impl->CopySurfaceFromTarget = &CopySurfaceFromTarget;
+246
tests/replace-image/main.c
··· 1 + #include "SDL.h" 2 + #include "SDL_gpu.h" 3 + #include <math.h> 4 + #include "common.h" 5 + #include "compat.h" 6 + 7 + 8 + 9 + void set_pixel(SDL_Surface* surface, int x, int y, Uint32 color) 10 + { 11 + int bpp; 12 + Uint8* bits; 13 + 14 + if(surface == NULL || x < 0 || y < 0 || x >= surface->w || y >= surface->h) 15 + return; 16 + 17 + bpp = surface->format->BytesPerPixel; 18 + bits = ((Uint8 *)surface->pixels) + y*surface->pitch + x*bpp; 19 + 20 + /* Set the pixel */ 21 + switch(bpp) 22 + { 23 + case 1: 24 + *((Uint8 *)(bits)) = (Uint8)color; 25 + break; 26 + case 2: 27 + *((Uint16 *)(bits)) = (Uint16)color; 28 + break; 29 + case 3: { /* Format/endian independent */ 30 + Uint8 r,g,b; 31 + r = (color >> surface->format->Rshift) & 0xFF; 32 + g = (color >> surface->format->Gshift) & 0xFF; 33 + b = (color >> surface->format->Bshift) & 0xFF; 34 + *((bits)+surface->format->Rshift/8) = r; 35 + *((bits)+surface->format->Gshift/8) = g; 36 + *((bits)+surface->format->Bshift/8) = b; 37 + } 38 + break; 39 + case 4: 40 + *((Uint32 *)(bits)) = (Uint32)color; 41 + break; 42 + } 43 + } 44 + 45 + 46 + int main(int argc, char* argv[]) 47 + { 48 + GPU_Target* screen; 49 + 50 + printRenderers(); 51 + 52 + screen = GPU_Init(800, 600, GPU_DEFAULT_INIT_FLAGS); 53 + if(screen == NULL) 54 + return 1; 55 + 56 + printCurrentRenderer(); 57 + 58 + { 59 + Uint32 startTime; 60 + long frameCount; 61 + Uint8 done; 62 + SDL_Event event; 63 + 64 + Uint32 rmask, gmask, bmask, amask; 65 + int num_surfaces = 4; 66 + SDL_Surface* surfaces[4]; 67 + int i; 68 + int current_surface = 0; 69 + 70 + SDL_Color red = {255, 0, 0, 255}; 71 + SDL_Color white = {255, 255, 255, 255}; 72 + 73 + GPU_Rect surface_rect = {50, 70, 100, 100}; 74 + 75 + SDL_Color border_color = {255, 255, 255, 255}; 76 + SDL_Color surface_rect_color = {0, 255, 0, 255}; 77 + 78 + const Uint8* keystates = SDL_GetKeyState(NULL); 79 + SDL_Keymod kmod; 80 + 81 + int mx, my; 82 + Uint32 mouse_state; 83 + 84 + GPU_Image* image; 85 + GPU_Image* selection_image; 86 + 87 + #if SDL_BYTEORDER == SDL_BIG_ENDIAN 88 + rmask = 0xff000000; 89 + gmask = 0x00ff0000; 90 + bmask = 0x0000ff00; 91 + amask = 0x000000ff; 92 + #else 93 + rmask = 0x000000ff; 94 + gmask = 0x0000ff00; 95 + bmask = 0x00ff0000; 96 + amask = 0xff000000; 97 + #endif 98 + 99 + // Create surfaces which will replace the main image 100 + surfaces[0] = GPU_LoadSurface("data/test.bmp"); 101 + if(surfaces[0] == NULL) 102 + return 2; 103 + 104 + for(i = 1; i < num_surfaces; ++i) 105 + { 106 + surfaces[i] = SDL_CreateRGBSurface(SDL_SWSURFACE, 50 * (i+1), 40 * (i+1), 32, 107 + rmask, gmask, bmask, amask); 108 + if(surfaces[i] == NULL) 109 + return 3; 110 + 111 + SDL_FillRect(surfaces[i], NULL, SDL_MapRGBA(surfaces[i]->format, rand()%256, rand()%256, rand()%256, 255)); 112 + } 113 + 114 + image = GPU_CopyImageFromSurface(surfaces[0]); 115 + if(image == NULL) 116 + return 4; 117 + 118 + selection_image = GPU_CopyImageFromSurface(surfaces[0]); 119 + if(selection_image == NULL) 120 + return 5; 121 + 122 + // Fade out the selection image 123 + GPU_SetColor(selection_image, GPU_MakeColor(255, 255, 255, 100)); 124 + GPU_SetBlending(selection_image, 1); 125 + 126 + if(!GPU_LoadTarget(image)) 127 + return 6; 128 + 129 + startTime = SDL_GetTicks(); 130 + frameCount = 0; 131 + 132 + done = 0; 133 + while(!done) 134 + { 135 + while(SDL_PollEvent(&event)) 136 + { 137 + if(event.type == SDL_QUIT) 138 + done = 1; 139 + else if(event.type == SDL_KEYDOWN) 140 + { 141 + if(event.key.keysym.sym == SDLK_ESCAPE) 142 + done = 1; 143 + if(event.key.keysym.sym == SDLK_r) 144 + { 145 + GPU_Clear(image->target); 146 + } 147 + if(event.key.keysym.sym == SDLK_SPACE) 148 + { 149 + // Replace images with the next surface 150 + current_surface++; 151 + if(current_surface >= num_surfaces) 152 + current_surface = 0; 153 + 154 + GPU_ReplaceImage(image, surfaces[current_surface], NULL); 155 + GPU_ReplaceImage(selection_image, surfaces[current_surface], NULL); 156 + } 157 + if(event.key.keysym.sym == SDLK_RETURN) 158 + { 159 + // Replace the main image with a section of the current source surface 160 + GPU_ReplaceImage(image, surfaces[current_surface], &surface_rect); 161 + } 162 + } 163 + } 164 + 165 + kmod = SDL_GetModState(); 166 + 167 + // Adjust source rectangle 168 + if(keystates[KEY_UP]) 169 + { 170 + if(kmod & KMOD_SHIFT) 171 + surface_rect.h -= 1; 172 + else 173 + surface_rect.y -= 1; 174 + } 175 + if(keystates[KEY_DOWN]) 176 + { 177 + if(kmod & KMOD_SHIFT) 178 + surface_rect.h += 1; 179 + else 180 + surface_rect.y += 1; 181 + } 182 + if(keystates[KEY_LEFT]) 183 + { 184 + if(kmod & KMOD_SHIFT) 185 + surface_rect.w -= 1; 186 + else 187 + surface_rect.x -= 1; 188 + } 189 + if(keystates[KEY_RIGHT]) 190 + { 191 + if(kmod & KMOD_SHIFT) 192 + surface_rect.w += 1; 193 + else 194 + surface_rect.x += 1; 195 + } 196 + 197 + // Scribble some pixels on the current main image 198 + mouse_state = SDL_GetMouseState(&mx, &my); 199 + if(mouse_state & SDL_BUTTON_LMASK) 200 + { 201 + GPU_Pixel(image->target, mx + image->w/2 - screen->w/2, my + image->h/2 - screen->h/2, red); 202 + } 203 + if(mouse_state & SDL_BUTTON_RMASK) 204 + { 205 + GPU_Pixel(image->target, mx + image->w/2 - screen->w/2, my + image->h/2 - screen->h/2, white); 206 + } 207 + 208 + GPU_Clear(screen); 209 + 210 + // Draw selection image 211 + GPU_Blit(selection_image, NULL, screen, selection_image->w/2, selection_image->h/2); 212 + GPU_Rectangle(screen, 0, 0, selection_image->w, selection_image->h, border_color); 213 + 214 + // Draw source region 215 + GPU_Rectangle(screen, surface_rect.x, surface_rect.y, 216 + surface_rect.x + surface_rect.w, surface_rect.y + surface_rect.h, surface_rect_color); 217 + 218 + // Draw replaceable main image 219 + GPU_Blit(image, NULL, screen, screen->w/2, screen->h/2); 220 + GPU_Rectangle(screen, screen->w/2 - image->w/2, screen->h/2 - image->h/2, 221 + screen->w/2 + image->w/2, screen->h/2 + image->h/2, border_color); 222 + 223 + GPU_Flip(screen); 224 + 225 + frameCount++; 226 + if(frameCount%500 == 0) 227 + printf("Average FPS: %.2f\n", 1000.0f*frameCount/(SDL_GetTicks() - startTime)); 228 + } 229 + 230 + printf("Average FPS: %.2f\n", 1000.0f*frameCount/(SDL_GetTicks() - startTime)); 231 + 232 + GPU_FreeImage(selection_image); 233 + GPU_FreeImage(image); 234 + 235 + for(i = 0; i < num_surfaces; ++i) 236 + { 237 + SDL_FreeSurface(surfaces[i]); 238 + } 239 + } 240 + 241 + GPU_Quit(); 242 + 243 + return 0; 244 + } 245 + 246 +