INLINE void render_quad(sdl_info *sdl, texture_info *texture, render_primitive *prim, int x, int y) { SDL_Texture *texture_id; SDL_Rect target_rect; target_rect.x = x; target_rect.y = y; target_rect.w = round_nearest(prim->bounds.x1 - prim->bounds.x0); target_rect.h = round_nearest(prim->bounds.y1 - prim->bounds.y0); if (texture) { texture_id = texture->texture_id; texture->copyinfo->time -= osd_ticks(); #if 0 if ((PRIMFLAG_GET_SCREENTEX(prim->flags)) && video_config.filter) { SDL_SetTextureScaleMode(texture->texture_id, DRAW2_SCALEMODE_BEST); } else { SDL_SetTextureScaleMode(texture->texture_id, DRAW2_SCALEMODE_NEAREST); } #endif SDL_SetTextureBlendMode(texture_id, texture->sdl_blendmode); set_coloralphamode(texture_id, &prim->color); SDL_RenderCopy(sdl->sdl_renderer, texture_id, NULL, &target_rect); texture->copyinfo->time += osd_ticks(); texture->copyinfo->pixel_count += MAX(STAT_PIXEL_THRESHOLD , (texture->rawwidth * texture->rawheight)); if (sdl->last_blit_pixels) { texture->copyinfo->time += (sdl->last_blit_time * (INT64) (texture->rawwidth * texture->rawheight)) / (INT64) sdl->last_blit_pixels; } texture->copyinfo->samples++; texture->copyinfo->perf = ( texture->copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->copyinfo->time; } else { UINT32 sr = (UINT32)(255.0f * prim->color.r); UINT32 sg = (UINT32)(255.0f * prim->color.g); UINT32 sb = (UINT32)(255.0f * prim->color.b); UINT32 sa = (UINT32)(255.0f * prim->color.a); SDL_SetRenderDrawBlendMode(sdl->sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); SDL_SetRenderDrawColor(sdl->sdl_renderer, sr, sg, sb, sa); SDL_RenderFillRect(sdl->sdl_renderer, &target_rect); } }
int LoadSprite(char *file) { int i; SDL_Surface *temp; /* Load the sprite image */ temp = SDL_LoadBMP(file); if (temp == NULL) { fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError()); return (-1); } sprite_w = temp->w; sprite_h = temp->h; /* Set transparent pixel as the pixel at (0,0) */ if (temp->format->palette) { SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint8 *) temp->pixels); } else { switch (temp->format->BitsPerPixel) { case 15: SDL_SetColorKey(temp, SDL_SRCCOLORKEY, (*(Uint16 *) temp->pixels) & 0x00007FFF); break; case 16: SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint16 *) temp->pixels); break; case 24: SDL_SetColorKey(temp, SDL_SRCCOLORKEY, (*(Uint32 *) temp->pixels) & 0x00FFFFFF); break; case 32: SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint32 *) temp->pixels); break; } } /* Create textures from the image */ for (i = 0; i < state->num_windows; ++i) { SDL_SelectRenderer(state->windows[i]); sprites[i] = SDL_CreateTextureFromSurface(0, temp); if (!sprites[i]) { SDL_SetColorKey(temp, 0, 0); sprites[i] = SDL_CreateTextureFromSurface(0, temp); } if (!sprites[i]) { fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError()); SDL_FreeSurface(temp); return (-1); } SDL_SetTextureBlendMode(sprites[i], blendMode); SDL_SetTextureScaleMode(sprites[i], scaleMode); } SDL_FreeSurface(temp); /* We're ready to roll. :) */ return (0); }
void SDL_ANDROID_VideoContextRecreated() { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Sending SDL_VIDEORESIZE event %dx%d", SDL_ANDROID_sFakeWindowWidth, SDL_ANDROID_sFakeWindowHeight); //SDL_PrivateResize(SDL_ANDROID_sFakeWindowWidth, SDL_ANDROID_sFakeWindowHeight); if ( SDL_ProcessEvents[SDL_VIDEORESIZE] == SDL_ENABLE ) { SDL_Event event; event.type = SDL_VIDEORESIZE; event.resize.w = SDL_ANDROID_sFakeWindowWidth; event.resize.h = SDL_ANDROID_sFakeWindowHeight; if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { SDL_PushEvent(&event); } } if( ! sdl_opengl ) { int i; SDL_SelectRenderer(SDL_VideoWindow); // Re-apply glOrtho() and blend modes // Re-apply our custom 4:3 screen aspect ratio glViewport(0, 0, SDL_ANDROID_sRealWindowWidth, SDL_ANDROID_sRealWindowHeight); glOrthof(0.0, (GLfloat) SDL_ANDROID_sWindowWidth, (GLfloat) SDL_ANDROID_sWindowHeight, 0.0, 0.0, 1.0); for( i = 0; i < HwSurfaceCount; i++ ) { // Allocate HW texture Uint32 format = PixelFormatEnumColorkey; // 1-bit alpha for color key, every surface will have colorkey so it's easier for us if( HwSurfaceList[i]->format->Amask ) format = PixelFormatEnumAlpha; if( HwSurfaceList[i] == SDL_CurrentVideoSurface ) format = PixelFormatEnum; HwSurfaceList[i]->hwdata = (struct private_hwdata *)SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, HwSurfaceList[i]->w, HwSurfaceList[i]->h); if( !HwSurfaceList[i]->hwdata ) { SDL_OutOfMemory(); return; } if( SDL_ANDROID_SmoothVideo ) SDL_SetTextureScaleMode((SDL_Texture *)HwSurfaceList[i]->hwdata, SDL_SCALEMODE_SLOW); ANDROID_UnlockHWSurface(NULL, HwSurfaceList[i]); // Re-fill texture with graphics } } };
static int ANDROID_LockHWSurface(_THIS, SDL_Surface *surface) { if( !SDL_ANDROID_InsideVideoThread() ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Error: calling %s not from the main thread!", __PRETTY_FUNCTION__); return -1; } if( surface == SDL_CurrentVideoSurface ) { // Copy pixels from pixelbuffer to video surface - this is slow! Uint16 * row = NULL; int fakeH = SDL_ANDROID_sFakeWindowHeight, fakeW = SDL_ANDROID_sFakeWindowWidth; int realH = SDL_ANDROID_sWindowHeight, realW = SDL_ANDROID_sWindowWidth; int x, y; if( ! SDL_CurrentVideoSurface->pixels ) { glPixelStorei(GL_PACK_ALIGNMENT, 1); SDL_CurrentVideoSurface->pixels = SDL_malloc(SDL_ANDROID_sFakeWindowWidth * SDL_ANDROID_sFakeWindowHeight * SDL_ANDROID_BYTESPERPIXEL); if ( ! SDL_CurrentVideoSurface->pixels ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate buffer for SDL_CurrentVideoSurface"); SDL_SetError("Couldn't allocate buffer for SDL_CurrentVideoSurface"); return(-1); } } if( ! SDL_CurrentVideoSurface->hwdata ) { SDL_CurrentVideoSurface->hwdata = (struct private_hwdata *)SDL_CreateTexture(PixelFormatEnum, SDL_TEXTUREACCESS_STATIC, SDL_ANDROID_sFakeWindowWidth, SDL_ANDROID_sFakeWindowHeight); if( !SDL_CurrentVideoSurface->hwdata ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate texture for SDL_CurrentVideoSurface"); SDL_OutOfMemory(); return(-1); } if( SDL_ANDROID_SmoothVideo ) SDL_SetTextureScaleMode((SDL_Texture *)SDL_CurrentVideoSurface->hwdata, SDL_SCALEMODE_SLOW); // Register main video texture to be recreated when needed HwSurfaceCount++; HwSurfaceList = SDL_realloc( HwSurfaceList, HwSurfaceCount * sizeof(SDL_Surface *) ); HwSurfaceList[HwSurfaceCount-1] = SDL_CurrentVideoSurface; DEBUGOUT("ANDROID_SetVideoMode() HwSurfaceCount %d HwSurfaceList %p", HwSurfaceCount, HwSurfaceList); } row = SDL_stack_alloc(Uint16, SDL_ANDROID_sWindowWidth); for(y=0; y<fakeH; y++) { // TODO: support 24bpp and 32bpp glReadPixels(0, realH - 1 - (realH * y / fakeH), realW, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, row); for(x=0; x<fakeW; x++) ((Uint16 *)SDL_CurrentVideoSurface->pixels)[ fakeW * y + x ] = row[ x * fakeW / realW ]; } SDL_stack_free(row); } if( !surface->hwdata ) return(-1); // Extra check not necessary /* if( SDL_CurrentVideoSurface->format->BitsPerPixel == surface->format->BitsPerPixel && SDL_CurrentVideoSurface->format->Rmask == surface->format->Rmask && SDL_CurrentVideoSurface->format->Gmask == surface->format->Gmask && SDL_CurrentVideoSurface->format->Bmask == surface->format->Bmask && SDL_CurrentVideoSurface->format->Amask == surface->format->Amask ) return(0); if( this->displayformatalphapixel->BitsPerPixel == surface->format->BitsPerPixel && this->displayformatalphapixel->Rmask == surface->format->Rmask && this->displayformatalphapixel->Gmask == surface->format->Gmask && this->displayformatalphapixel->Bmask == surface->format->Bmask && this->displayformatalphapixel->Amask == surface->format->Amask ) return(0); return(-1); */ return(0); }
static int ANDROID_AllocHWSurface(_THIS, SDL_Surface *surface) { if( !SDL_ANDROID_InsideVideoThread() ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Error: calling %s not from the main thread!", __PRETTY_FUNCTION__); return -1; } if ( ! (surface->w && surface->h) ) return(-1); DEBUGOUT("ANDROID_AllocHWSurface() surface %p w %d h %d", surface, surface->w, surface->h); Uint32 format = PixelFormatEnumColorkey; // 1-bit alpha for color key, every surface will have colorkey so it's easier for us if( surface->format->Amask ) { SDL_PixelFormat format1; int bpp; format = PixelFormatEnumAlpha; SDL_memset(&format1, 0, sizeof(format1)); SDL_PixelFormatEnumToMasks( format, &bpp, &format1.Rmask, &format1.Gmask, &format1.Bmask, &format1.Amask ); if( surface->format->BitsPerPixel != bpp || surface->format->Rmask != format1.Rmask || surface->format->Gmask != format1.Gmask || surface->format->Bmask != format1.Bmask || surface->format->Amask != format1.Amask ) return(-1); // Do not allow alpha-surfaces with format other than RGBA4444 (it will be pain to lock/copy them) } else { // HW-accel surface should be RGB565 if( !( SDL_CurrentVideoSurface->format->BitsPerPixel == surface->format->BitsPerPixel && SDL_CurrentVideoSurface->format->Rmask == surface->format->Rmask && SDL_CurrentVideoSurface->format->Gmask == surface->format->Gmask && SDL_CurrentVideoSurface->format->Bmask == surface->format->Bmask && SDL_CurrentVideoSurface->format->Amask == surface->format->Amask ) ) return(-1); } surface->pitch = surface->w * surface->format->BytesPerPixel; surface->pixels = SDL_malloc(surface->h * surface->w * surface->format->BytesPerPixel); if ( surface->pixels == NULL ) { SDL_OutOfMemory(); return(-1); } SDL_memset(surface->pixels, 0, surface->h*surface->pitch); surface->hwdata = (struct private_hwdata *)SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, surface->w, surface->h); if( !surface->hwdata ) { SDL_free(surface->pixels); surface->pixels = NULL; SDL_OutOfMemory(); return(-1); } if( SDL_ANDROID_SmoothVideo ) SDL_SetTextureScaleMode((SDL_Texture *)surface->hwdata, SDL_SCALEMODE_SLOW); if( surface->format->Amask ) { SDL_SetTextureAlphaMod((struct SDL_Texture *)surface->hwdata, SDL_ALPHA_OPAQUE); SDL_SetTextureBlendMode((struct SDL_Texture *)surface->hwdata, SDL_BLENDMODE_BLEND); } surface->flags |= SDL_HWSURFACE | SDL_HWACCEL; HwSurfaceCount++; DEBUGOUT("ANDROID_AllocHWSurface() in HwSurfaceCount %d HwSurfaceList %p", HwSurfaceCount, HwSurfaceList); HwSurfaceList = SDL_realloc( HwSurfaceList, HwSurfaceCount * sizeof(SDL_Surface *) ); DEBUGOUT("ANDROID_AllocHWSurface() out HwSurfaceCount %d HwSurfaceList %p", HwSurfaceCount, HwSurfaceList); HwSurfaceList[HwSurfaceCount-1] = surface; return 0; }
SDL_Surface *ANDROID_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { SDL_PixelFormat format; int bpp1; __android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_SetVideoMode(): application requested mode %dx%d OpenGL %d HW %d BPP %d", width, height, flags & SDL_OPENGL, flags & SDL_HWSURFACE, SDL_ANDROID_BITSPERPIXEL); if( ! SDL_ANDROID_InsideVideoThread() ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Error: calling %s not from the main thread!", __PRETTY_FUNCTION__); return NULL; } sdl_opengl = (flags & SDL_OPENGL) ? 1 : 0; SDL_ANDROID_sFakeWindowWidth = width; SDL_ANDROID_sFakeWindowHeight = height; current->flags = (flags & SDL_FULLSCREEN) | (flags & SDL_OPENGL) | SDL_DOUBLEBUF | ( flags & SDL_HWSURFACE ); current->w = width; current->h = height; current->pitch = SDL_ANDROID_sFakeWindowWidth * SDL_ANDROID_BYTESPERPIXEL; current->pixels = NULL; current->hwdata = NULL; HwSurfaceCount = 0; HwSurfaceList = NULL; DEBUGOUT("ANDROID_SetVideoMode() HwSurfaceCount %d HwSurfaceList %p", HwSurfaceCount, HwSurfaceList); if( ! sdl_opengl ) { SDL_DisplayMode mode; SDL_RendererInfo SDL_VideoRendererInfo; SDL_SelectVideoDisplay(0); SDL_VideoWindow = SDL_CreateWindow("", 0, 0, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL); SDL_memset(&mode, 0, sizeof(mode)); mode.format = PixelFormatEnum; SDL_SetWindowDisplayMode(SDL_VideoWindow, &mode); if (SDL_CreateRenderer(SDL_VideoWindow, -1, 0) < 0) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_SetVideoMode(): Error creating renderer"); return NULL; } SDL_GetRendererInfo(&SDL_VideoRendererInfo); current->hwdata = NULL; if( ! (flags & SDL_HWSURFACE) ) { current->pixels = SDL_malloc(width * height * SDL_ANDROID_BYTESPERPIXEL); if ( ! current->pixels ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate buffer for requested mode"); SDL_SetError("Couldn't allocate buffer for requested mode"); return(NULL); } SDL_memset(current->pixels, 0, width * height * SDL_ANDROID_BYTESPERPIXEL); current->hwdata = (struct private_hwdata *)SDL_CreateTexture(PixelFormatEnum, SDL_TEXTUREACCESS_STATIC, width, height); if( !current->hwdata ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate texture for SDL_CurrentVideoSurface"); SDL_free(current->pixels); current->pixels = NULL; SDL_OutOfMemory(); return(NULL); } if( SDL_ANDROID_SmoothVideo ) SDL_SetTextureScaleMode((SDL_Texture *)current->hwdata, SDL_SCALEMODE_SLOW); // Register main video texture to be recreated when needed HwSurfaceCount++; HwSurfaceList = SDL_realloc( HwSurfaceList, HwSurfaceCount * sizeof(SDL_Surface *) ); HwSurfaceList[HwSurfaceCount-1] = current; DEBUGOUT("ANDROID_SetVideoMode() HwSurfaceCount %d HwSurfaceList %p", HwSurfaceCount, HwSurfaceList); } glViewport(0, 0, SDL_ANDROID_sRealWindowWidth, SDL_ANDROID_sRealWindowHeight); glOrthof(0.0, (GLfloat) SDL_ANDROID_sWindowWidth, (GLfloat) SDL_ANDROID_sWindowHeight, 0.0, 0.0, 1.0); } /* Allocate the new pixel format for the screen */ SDL_memset(&format, 0, sizeof(format)); SDL_PixelFormatEnumToMasks( PixelFormatEnum, &bpp1, &format.Rmask, &format.Gmask, &format.Bmask, &format.Amask ); format.BitsPerPixel = bpp1; format.BytesPerPixel = SDL_ANDROID_BYTESPERPIXEL; if ( ! SDL_ReallocFormat(current, SDL_ANDROID_BITSPERPIXEL, format.Rmask, format.Gmask, format.Bmask, format.Amask) ) { __android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate new pixel format for requested mode"); SDL_SetError("Couldn't allocate new pixel format for requested mode"); return(NULL); } /* Set up the new mode framebuffer */ SDL_CurrentVideoSurface = current; /* We're done */ return(current); }