From 9dd8b47bf4546c56071f79cd64ed64a995b6771a Mon Sep 17 00:00:00 2001 From: couriersud Date: Mon, 5 Jan 2015 01:54:24 +0100 Subject: Fixed a memory leak in draw13.c and a clipping issues with vertically flipped textures. Simplified the code and added consts were appropriate. This was a preparation for using SDL2.0 texture rotation going forward. (nw) --- src/osd/sdl/blit13.h | 10 +- src/osd/sdl/draw13.c | 658 +++++++++++++++++++++++++-------------------------- 2 files changed, 327 insertions(+), 341 deletions(-) diff --git a/src/osd/sdl/blit13.h b/src/osd/sdl/blit13.h index 9ae4040b42b..6b8de983dc2 100644 --- a/src/osd/sdl/blit13.h +++ b/src/osd/sdl/blit13.h @@ -113,13 +113,13 @@ INLINE UINT32 pixel_ycc_to_rgb_pal(UINT16 *pixel, const rgb_t *palette) //============================================================ #define TEXCOPY_M( _name, _src_type, _dest_type, _op, _len_div) \ -INLINE void texcopy_##_name (texture_info *texture, const render_texinfo *texsource) { \ +INLINE void texcopy_##_name (const texture_info *texture, const render_texinfo *texsource) { \ ATTR_UNUSED const rgb_t *palbase = texsource->palette(); \ int x, y; \ /* loop over Y */ \ for (y = 0; y < texsource->height; y++) { \ _src_type *src = (_src_type *)texsource->base + y * texsource->rowpixels / (_len_div); \ - _dest_type *dst = (_dest_type *)((UINT8 *)texture->pixels + y * texture->pitch); \ + _dest_type *dst = (_dest_type *)((UINT8 *)texture->m_pixels + y * texture->m_pitch); \ x = texsource->width / (_len_div); \ while (x > 0) { \ *dst++ = _op(*src); \ @@ -133,17 +133,17 @@ INLINE void texcopy_##_name (texture_info *texture, const render_texinfo *texsou TEXCOPY_M( _name, _src_type, _dest_type, _op, 1) #define TEXROT( _name, _src_type, _dest_type, _op) \ -INLINE void texcopy_rot_##_name (texture_info *texture, const render_texinfo *texsource) { \ +INLINE void texcopy_rot_##_name (const texture_info *texture, const render_texinfo *texsource) { \ ATTR_UNUSED const rgb_t *palbase = texsource->palette(); \ int x, y; \ - quad_setup_data *setup = &texture->setup; \ + const quad_setup_data *setup = &texture->m_setup; \ int dudx = setup->dudx; \ int dvdx = setup->dvdx; \ /* loop over Y */ \ for (y = 0; y < setup->rotheight; y++) { \ INT32 curu = setup->startu + y * setup->dudy; \ INT32 curv = setup->startv + y * setup->dvdy; \ - _dest_type *dst = (_dest_type *)((UINT8 *)texture->pixels + y * texture->pitch); \ + _dest_type *dst = (_dest_type *)((UINT8 *)texture->m_pixels + y * texture->m_pitch); \ x = setup->rotwidth; \ while (x>0) { \ _src_type *src = (_src_type *) texsource->base + (curv >> 16) * texsource->rowpixels + (curu >> 16); \ diff --git a/src/osd/sdl/draw13.c b/src/osd/sdl/draw13.c index f39c1396bf9..ecdc24771ad 100644 --- a/src/osd/sdl/draw13.c +++ b/src/osd/sdl/draw13.c @@ -43,15 +43,18 @@ enum //============================================================ -// MACROS +// Inline functions //============================================================ -#define IS_OPAQUE(a) (a >= 1.0f) -#define IS_TRANSPARENT(a) (a < 0.0001f) - -#define MAX4(a, b, c, d) MAX(a, MAX(b, MAX(c, d))) -#define MIN4(a, b, c, d) MIN(a, MIN(b, MIN(c, d))) +static inline bool is_opaque(const float &a) +{ + return (a >= 1.0f); +} +static inline bool is_transparent(const float &a) +{ + return (a < 0.0001f); +} //============================================================ // TYPES @@ -64,16 +67,18 @@ struct quad_setup_data : dudx(0), dvdx(0), dudy(0), dvdy(0), startu(0), startv(0), rotwidth(0), rotheight(0) {} + void compute(const render_primitive &prim); + INT32 dudx, dvdx, dudy, dvdy; INT32 startu, startv; INT32 rotwidth, rotheight; }; -struct texture_info; +class texture_info; -typedef void (*texture_copy_func)(texture_info *texture, const render_texinfo *texsource); +typedef void (*texture_copy_func)(const texture_info *texture, const render_texinfo *texsource); -struct copy_info { +struct copy_info_t { int src_fmt; Uint32 dst_fmt; int dst_bpp; @@ -88,71 +93,99 @@ struct copy_info { int samples; int perf; /* list */ - copy_info *next; + copy_info_t *next; }; +//============================================================ +// Textures +//============================================================ + +struct sdl_info; + /* texture_info holds information about a texture */ -struct texture_info +class texture_info { - texture_info() - : next(NULL), hash(0), flags(0), rawwidth(0), rawheight(0), format(0), - pixels(NULL), pitch(0), pixels_own(0), texture_id(NULL), copyinfo(NULL), - sdl_access(0), sdl_blendmode(SDL_BLENDMODE_NONE), is_rotated(0), last_access(0) - { - } - texture_info * next; // next texture in the list + friend class simple_list; +public: + texture_info(SDL_Renderer *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const UINT32 flags); + ~texture_info(); + + void set_data(const render_texinfo &texsource, const UINT32 flags); + void render_quad(const render_primitive *prim, const int x, const int y); + bool matches(const render_primitive &prim, const quad_setup_data &setup); + + copy_info_t *compute_size_type(); + + void *m_pixels; // pixels for the texture + int m_pitch; + + copy_info_t *m_copyinfo; + quad_setup_data m_setup; + + osd_ticks_t m_last_access; - HashT hash; // hash value for the texture (must be >= pointer size) - UINT32 flags; // rendering flags - render_texinfo texinfo; // copy of the texture info + int raw_width() const { return m_texinfo.width; } + int raw_height() const { return m_texinfo.height; } - int rawwidth, rawheight;// raw width/height of the texture + texture_info *next() { return m_next; } + const render_texinfo &texinfo() const { return m_texinfo; } + render_texinfo &texinfo() { return m_texinfo; } - int format; // texture format - void *pixels; // pixels for the texture - int pitch; - int pixels_own; // do we own / allocated it ? + const HashT hash() const { return m_hash; } + const UINT32 flags() const { return m_flags; } + const bool is_pixels_owned() const { // do we own / allocated it ? + return m_sdl_access == SDL_TEXTUREACCESS_STATIC + && m_copyinfo->func != NULL ; + } + +private: + SDL_Renderer * m_renderer; + render_texinfo m_texinfo; // copy of the texture info + HashT m_hash; // hash value for the texture (must be >= pointer size) + UINT32 m_flags; // rendering flags - SDL_Texture *texture_id; + SDL_Texture * m_texture_id; + int m_is_rotated; - copy_info *copyinfo; - Uint32 sdl_access; - SDL_BlendMode sdl_blendmode; - quad_setup_data setup; - int is_rotated; + int m_format; // texture format + SDL_BlendMode m_sdl_blendmode; + Uint32 m_sdl_access; - osd_ticks_t last_access; + texture_info * m_next; // next texture in the list }; /* sdl_info is the information about SDL for the current screen */ struct sdl_info { sdl_info() - : blittimer(0), extra_flags(0), sdl_renderer(NULL), texlist(NULL), - texture_max_width(0), texture_max_height(0), last_hofs(0), last_vofs(0), - resize_pending(0), resize_width(0), resize_height(0), - last_blit_time(0), last_blit_pixels(0) + : m_blittimer(0), m_renderer(NULL), + m_hofs(0), m_vofs(0), + m_resize_pending(0), m_resize_width(0), m_resize_height(0), + m_last_blit_time(0), m_last_blit_pixels(0) {} - INT32 blittimer; - UINT32 extra_flags; - SDL_Renderer *sdl_renderer; - texture_info * texlist; // list of active textures - INT32 texture_max_width; // texture maximum width - INT32 texture_max_height; // texture maximum height + void render_quad(texture_info *texture, const render_primitive *prim, const int x, const int y); + + texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); + texture_info *texture_update(const render_primitive &prim); - float last_hofs; - float last_vofs; + INT32 m_blittimer; + + SDL_Renderer * m_renderer; + simple_list m_texlist; // list of active textures + + float m_hofs; + float m_vofs; // resize information - UINT8 resize_pending; - UINT32 resize_width; - UINT32 resize_height; + UINT8 m_resize_pending; + UINT32 m_resize_width; + UINT32 m_resize_height; // Stats - INT64 last_blit_time; - INT64 last_blit_pixels; + INT64 m_last_blit_time; + INT64 m_last_blit_pixels; }; //============================================================ @@ -171,17 +204,6 @@ static render_primitive_list &drawsdl2_window_get_primitives(sdl_window_info *wi static void drawsdl2_destroy_all_textures(sdl_window_info *window); static void drawsdl2_window_clear(sdl_window_info *window); static int drawsdl2_xy_to_render_target(sdl_window_info *window, int x, int y, int *xt, int *yt); -static void drawsdl2_destroy_texture(sdl_info *sdl, texture_info *texture); - -//============================================================ -// Textures -//============================================================ - -static void texture_set_data(sdl_info *sdl, texture_info *texture, const render_texinfo *texsource, UINT32 flags); -static texture_info *texture_create(sdl_window_info *window, const render_texinfo *texsource, quad_setup_data *setup, UINT32 flags); -static texture_info *texture_find(sdl_info *sdl, const render_primitive *prim, quad_setup_data *setup); -static texture_info * texture_update(sdl_window_info *window, const render_primitive *prim); - //============================================================ // TEXCOPY FUNCS @@ -202,12 +224,12 @@ static texture_info * texture_update(sdl_window_info *window, const render_primi #define ENTRY_BM(a,b,c,d,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, c, d, texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} #define ENTRY_LR(a,b,c,d,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, c, d, texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} -static copy_info blit_info_default[] = +static copy_info_t blit_info_default[] = { /* no rotation */ ENTRY(ARGB32, ARGB8888, 4, 0, NULL), ENTRY_LR(ARGB32, RGB888, 4, 0, argb32_rgb32), - /* Entry for primarily for directfb */ + /* Entry primarily for directfb */ ENTRY_BM(ARGB32, RGB888, 4, 0, argb32_rgb32, SDL_BLENDMODE_ADD), ENTRY_BM(ARGB32, RGB888, 4, 0, argb32_rgb32, SDL_BLENDMODE_MOD), ENTRY_BM(ARGB32, RGB888, 4, 0, argb32_rgb32, SDL_BLENDMODE_NONE), @@ -247,7 +269,7 @@ static copy_info blit_info_default[] = /* rotation */ ENTRY(ARGB32, ARGB8888, 4, 1, rot_argb32_argb32), ENTRY_LR(ARGB32, RGB888, 4, 1, rot_argb32_rgb32), - /* Entry for primarily for directfb */ + /* Entry primarily for directfb */ ENTRY_BM(ARGB32, RGB888, 4, 1, rot_argb32_rgb32, SDL_BLENDMODE_ADD), ENTRY_BM(ARGB32, RGB888, 4, 1, rot_argb32_rgb32, SDL_BLENDMODE_MOD), ENTRY_BM(ARGB32, RGB888, 4, 1, rot_argb32_rgb32, SDL_BLENDMODE_NONE), @@ -281,7 +303,7 @@ static copy_info blit_info_default[] = { -1 }, }; -static copy_info *blit_info[SDL_TEXFORMAT_LAST+1]; +static copy_info_t *blit_info[SDL_TEXFORMAT_LAST+1]; static struct { @@ -300,12 +322,12 @@ INLINE float round_nearest(float f) return floor(f + 0.5f); } -INLINE HashT texture_compute_hash(const render_texinfo *texture, UINT32 flags) +INLINE HashT texture_compute_hash(const render_texinfo &texture, const UINT32 flags) { - return (HashT)texture->base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); + return (HashT)texture.base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); } -INLINE SDL_BlendMode map_blendmode(int blendmode) +INLINE SDL_BlendMode map_blendmode(const int blendmode) { switch (blendmode) { @@ -331,19 +353,19 @@ INLINE void set_coloralphamode(SDL_Texture *texture_id, const render_color *col UINT32 sa = (UINT32)(255.0f * color->a); - if (color->r >= 1.0f && color->g >= 1.0f && color->b >= 1.0f && IS_OPAQUE(color->a)) + if (color->r >= 1.0f && color->g >= 1.0f && color->b >= 1.0f && is_opaque(color->a)) { SDL_SetTextureColorMod(texture_id, 0xFF, 0xFF, 0xFF); SDL_SetTextureAlphaMod(texture_id, 0xFF); } /* coloring-only case */ - else if (IS_OPAQUE(color->a)) + else if (is_opaque(color->a)) { SDL_SetTextureColorMod(texture_id, sr, sg, sb); SDL_SetTextureAlphaMod(texture_id, 0xFF); } /* alpha and/or coloring case */ - else if (!IS_TRANSPARENT(color->a)) + else if (!is_transparent(color->a)) { SDL_SetTextureColorMod(texture_id, sr, sg, sb); SDL_SetTextureAlphaMod(texture_id, sa); @@ -355,9 +377,8 @@ INLINE void set_coloralphamode(SDL_Texture *texture_id, const render_color *col } } -INLINE void render_quad(sdl_info *sdl, texture_info *texture, render_primitive *prim, int x, int y) +void texture_info::render_quad(const render_primitive *prim, const int x, const int y) { - SDL_Texture *texture_id; SDL_Rect target_rect; target_rect.x = x; @@ -365,64 +386,59 @@ INLINE void render_quad(sdl_info *sdl, texture_info *texture, render_primitive * 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); - } + // no longer supported in SDL2 + if ((PRIMFLAG_GET_SCREENTEX(prim->m_flags)) && video_config.filter) + { + SDL_SetTextureScaleMode(texture->m_texture_id, DRAW2_SCALEMODE_BEST); + } + else + { + SDL_SetTextureScaleMode(texture->m_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); - } + SDL_SetTextureBlendMode(m_texture_id, m_sdl_blendmode); + set_coloralphamode(m_texture_id, &prim->color); + SDL_RenderCopy(m_renderer, m_texture_id, NULL, &target_rect); } -#if 0 -static int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat) +void sdl_info::render_quad(texture_info *texture, const render_primitive *prim, const int x, const int y) { - struct SDL_RendererInfo render_info; - int i; + SDL_Rect target_rect; - SDL_GetRendererInfo(&render_info); + 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); - for (i=0; i < render_info.num_texture_formats; i++) - { - if (format == render_info.texture_formats[i]) - return 1; - } - osd_printf_verbose("Pixelformat <%s> not supported\n", sformat); - return 0; + if (texture) + { + copy_info_t *copyinfo = texture->m_copyinfo; + copyinfo->time -= osd_ticks(); + texture->render_quad(prim, x, y); + copyinfo->time += osd_ticks(); + + copyinfo->pixel_count += MAX(STAT_PIXEL_THRESHOLD , (texture->raw_width() * texture->raw_height())); + if (m_last_blit_pixels) + { + copyinfo->time += (m_last_blit_time * (INT64) (texture->raw_width() * texture->raw_height())) / (INT64) m_last_blit_pixels; + } + copyinfo->samples++; + copyinfo->perf = ( texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->m_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(m_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); + SDL_SetRenderDrawColor(m_renderer, sr, sg, sb, sa); + SDL_RenderFillRect(m_renderer, &target_rect); + } } -#else + static int RendererSupportsFormat(SDL_Renderer *renderer, Uint32 format, Uint32 access, const char *sformat) { int i; @@ -449,15 +465,14 @@ static int RendererSupportsFormat(SDL_Renderer *renderer, Uint32 format, Uint32 fmt_support[i].status = 0; return 0; } -#endif //============================================================ // drawsdl2_init //============================================================ -static void add_list(copy_info **head, copy_info *element, Uint32 bm) +static void add_list(copy_info_t **head, copy_info_t *element, Uint32 bm) { - copy_info *newci = global_alloc(copy_info); + copy_info_t *newci = global_alloc(copy_info_t); *newci = *element; newci->bm_mask = bm; @@ -465,9 +480,9 @@ static void add_list(copy_info **head, copy_info *element, Uint32 bm) *head = newci; } -static void expand_copy_info(copy_info *list) +static void expand_copy_info(copy_info_t *list) { - copy_info *bi; + copy_info_t *bi; for (bi = list; bi->src_fmt != -1; bi++) { @@ -506,7 +521,7 @@ int drawsdl2_init(running_machine &machine, sdl_draw_info *callbacks) // No fatalerror here since not all video drivers support GL ! if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==NULL - osd_printf_verbose("Warning: Unable to load opengl library: %s\n", stemp ? stemp : ""); + osd_printf_warning("Warning: Unable to load opengl library: %s\n", stemp ? stemp : ""); else osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : ""); @@ -521,7 +536,7 @@ int drawsdl2_init(running_machine &machine, sdl_draw_info *callbacks) static void drawsdl2_exit(void) { int i; - copy_info *bi, *freeme; + copy_info_t *bi, *freeme; for (i = 0; i <= SDL_TEXFORMAT_LAST; i++) for (bi = blit_info[i]; bi != NULL; ) { @@ -565,12 +580,12 @@ static int drawsdl2_window_create(sdl_window_info *window, int width, int height window->dxdata = sdl; - sdl->extra_flags = (window->fullscreen() ? + UINT32 extra_flags = (window->fullscreen() ? SDL_WINDOW_BORDERLESS | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE); // create the SDL window window->sdl_window = SDL_CreateWindow(window->title, window->monitor()->monitor_x, 0, - width, height, sdl->extra_flags); + width, height, extra_flags); if (window->fullscreen() && video_config.switchres) { @@ -608,11 +623,11 @@ static int drawsdl2_window_create(sdl_window_info *window, int width, int height // create renderer if (video_config.waitvsync) - sdl->sdl_renderer = SDL_CreateRenderer(window->sdl_window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + sdl->m_renderer = SDL_CreateRenderer(window->sdl_window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); else - sdl->sdl_renderer = SDL_CreateRenderer(window->sdl_window, -1, SDL_RENDERER_ACCELERATED); + sdl->m_renderer = SDL_CreateRenderer(window->sdl_window, -1, SDL_RENDERER_ACCELERATED); - if (!sdl->sdl_renderer) + if (!sdl->m_renderer) { fatalerror("Error on creating renderer: %s\n", SDL_GetError()); } @@ -625,14 +640,9 @@ static int drawsdl2_window_create(sdl_window_info *window, int width, int height SDL_GetWindowSize(window->sdl_window, &window->width, &window->height); - sdl->blittimer = 3; + sdl->m_blittimer = 3; - // in case any textures try to come up before these are validated, - // OpenGL guarantees all implementations can handle something this size. - sdl->texture_max_width = 64; - sdl->texture_max_height = 64; - - SDL_RenderPresent(sdl->sdl_renderer); + SDL_RenderPresent(sdl->m_renderer); osd_printf_verbose("Leave drawsdl2_window_create\n"); return 0; } @@ -645,14 +655,14 @@ static void drawsdl2_window_resize(sdl_window_info *window, int width, int heigh { sdl_info *sdl = (sdl_info *) window->dxdata; - sdl->resize_pending = 1; - sdl->resize_height = height; - sdl->resize_width = width; + sdl->m_resize_pending = 1; + sdl->m_resize_height = height; + sdl->m_resize_width = width; window->width = width; window->height = height; - sdl->blittimer = 3; + sdl->m_blittimer = 3; } @@ -664,8 +674,8 @@ static int drawsdl2_xy_to_render_target(sdl_window_info *window, int x, int y, i { sdl_info *sdl = (sdl_info *) window->dxdata; - *xt = x - sdl->last_hofs; - *yt = y - sdl->last_vofs; + *xt = x - sdl->m_hofs; + *yt = y - sdl->m_vofs; if (*xt<0 || *xt >= window->blitwidth) return 0; if (*yt<0 || *yt >= window->blitheight) @@ -708,24 +718,24 @@ static int drawsdl2_window_draw(sdl_window_info *window, UINT32 dc, int update) return 0; } - if (sdl->resize_pending) + if (sdl->m_resize_pending) { - SDL_SetWindowSize(window->sdl_window, sdl->resize_width, sdl->resize_height); + SDL_SetWindowSize(window->sdl_window, sdl->m_resize_width, sdl->m_resize_height); SDL_GetWindowSize(window->sdl_window, &window->width, &window->height); - sdl->resize_pending = 0; - SDL_RenderSetViewport(sdl->sdl_renderer, NULL); + sdl->m_resize_pending = 0; + SDL_RenderSetViewport(sdl->m_renderer, NULL); } //SDL_SelectRenderer(window->sdl_window); - if (sdl->blittimer > 0) + if (sdl->m_blittimer > 0) { /* SDL Underlays need alpha = 0 ! */ - SDL_SetRenderDrawBlendMode(sdl->sdl_renderer, SDL_BLENDMODE_NONE); + SDL_SetRenderDrawBlendMode(sdl->m_renderer, SDL_BLENDMODE_NONE); //SDL_SetRenderDrawColor(0,0,0,255); - SDL_SetRenderDrawColor(sdl->sdl_renderer, 0,0,0,0); - SDL_RenderFillRect(sdl->sdl_renderer, NULL); - sdl->blittimer--; + SDL_SetRenderDrawColor(sdl->m_renderer, 0,0,0,0); + SDL_RenderFillRect(sdl->m_renderer, NULL); + sdl->m_blittimer--; } // compute centering parameters @@ -756,8 +766,8 @@ static int drawsdl2_window_draw(sdl_window_info *window, UINT32 dc, int update) } } - sdl->last_hofs = hofs; - sdl->last_vofs = vofs; + sdl->m_hofs = hofs; + sdl->m_vofs = vofs; window->primlist->acquire_lock(); @@ -774,16 +784,16 @@ static int drawsdl2_window_draw(sdl_window_info *window, UINT32 dc, int update) sb = (int)(255.0f * prim->color.b); sa = (int)(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_RenderDrawLine(sdl->sdl_renderer, prim->bounds.x0 + hofs, prim->bounds.y0 + vofs, + SDL_SetRenderDrawBlendMode(sdl->m_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); + SDL_SetRenderDrawColor(sdl->m_renderer, sr, sg, sb, sa); + SDL_RenderDrawLine(sdl->m_renderer, prim->bounds.x0 + hofs, prim->bounds.y0 + vofs, prim->bounds.x1 + hofs, prim->bounds.y1 + vofs); break; case render_primitive::QUAD: - texture = texture_update(window, prim); + texture = sdl->texture_update(*prim); if (texture) - blit_pixels += (texture->rawheight * texture->rawwidth); - render_quad(sdl, texture, prim, + blit_pixels += (texture->raw_height() * texture->raw_width()); + sdl->render_quad(texture, prim, round_nearest(hofs + prim->bounds.x0), round_nearest(vofs + prim->bounds.y0)); break; @@ -794,10 +804,10 @@ static int drawsdl2_window_draw(sdl_window_info *window, UINT32 dc, int update) window->primlist->release_lock(); - sdl->last_blit_pixels = blit_pixels; - sdl->last_blit_time = -osd_ticks(); - SDL_RenderPresent(sdl->sdl_renderer); - sdl->last_blit_time += osd_ticks(); + sdl->m_last_blit_pixels = blit_pixels; + sdl->m_last_blit_time = -osd_ticks(); + SDL_RenderPresent(sdl->m_renderer); + sdl->m_last_blit_time += osd_ticks(); return 0; } @@ -811,7 +821,7 @@ static void drawsdl2_window_clear(sdl_window_info *window) { sdl_info *sdl = (sdl_info *) window->dxdata; - sdl->blittimer = 2; + sdl->m_blittimer = 2; } @@ -845,26 +855,26 @@ static void drawsdl2_window_destroy(sdl_window_info *window) // texture_compute_size and type //============================================================ -static copy_info *texture_compute_size_type(SDL_Renderer *renderer, const render_texinfo *texsource, texture_info *texture, UINT32 flags) +copy_info_t *texture_info::compute_size_type() { - copy_info *bi; - copy_info *result = NULL; + copy_info_t *bi; + copy_info_t *result = NULL; int maxperf = 0; - //int bm = PRIMFLAG_GET_BLENDMODE(flags); - for (bi = blit_info[texture->format]; bi != NULL; bi = bi->next) + for (bi = blit_info[m_format]; bi != NULL; bi = bi->next) { - if ((texture->is_rotated == bi->rotate) - && (texture->sdl_blendmode == bi->bm_mask)) + if ((m_is_rotated == bi->rotate) + && (m_sdl_blendmode == bi->bm_mask)) { - if (RendererSupportsFormat(renderer, bi->dst_fmt, texture->sdl_access, bi->dstname)) + if (RendererSupportsFormat(m_renderer, bi->dst_fmt, m_sdl_access, bi->dstname)) { - if (bi->perf == 0) + int perf = bi->perf; + if (perf == 0) return bi; - else if (bi->perf > (maxperf * 102) / 100) + else if (perf > (maxperf * 102) / 100) { result = bi; - maxperf = bi->perf; + maxperf = perf; } } } @@ -872,11 +882,11 @@ static copy_info *texture_compute_size_type(SDL_Renderer *renderer, const render if (result) return result; /* try last resort handlers */ - for (bi = blit_info[texture->format]; bi != NULL; bi = bi->next) + for (bi = blit_info[m_format]; bi != NULL; bi = bi->next) { - if ((texture->is_rotated == bi->rotate) - && (texture->sdl_blendmode == bi->bm_mask)) - if (RendererSupportsFormat(renderer, bi->dst_fmt, texture->sdl_access, bi->dstname)) + if ((m_is_rotated == bi->rotate) + && (m_sdl_blendmode == bi->bm_mask)) + if (RendererSupportsFormat(m_renderer, bi->dst_fmt, m_sdl_access, bi->dstname)) return bi; } //FIXME: crash implement a -do nothing handler */ @@ -884,145 +894,162 @@ static copy_info *texture_compute_size_type(SDL_Renderer *renderer, const render } //============================================================ -// texture_create +// texture_info::matches //============================================================ -static texture_info *texture_create(sdl_window_info *window, const render_texinfo *texsource, quad_setup_data *setup, UINT32 flags) +bool texture_info::matches(const render_primitive &prim, const quad_setup_data &setup) { - sdl_info *sdl = (sdl_info *) window->dxdata; - texture_info *texture; + return texinfo().base == prim.texture.base && + texinfo().width == prim.texture.width && + texinfo().height == prim.texture.height && + texinfo().rowpixels == prim.texture.rowpixels && + m_setup.dudx == setup.dudx && + m_setup.dvdx == setup.dvdx && + m_setup.dudy == setup.dudy && + m_setup.dvdy == setup.dvdy && + ((flags() ^ prim.flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0; +} + +//============================================================ +// texture_create +//============================================================ - // allocate a new texture - texture = global_alloc(texture_info); +texture_info::texture_info(SDL_Renderer *renderer, const render_texinfo &texsource, const quad_setup_data &setup, UINT32 flags) +{ // fill in the core data - texture->hash = texture_compute_hash(texsource, flags); - texture->flags = flags; - texture->texinfo = *texsource; - texture->texinfo.seqid = -1; // force set data - texture->is_rotated = FALSE; - texture->setup = *setup; - texture->sdl_blendmode = map_blendmode(PRIMFLAG_GET_BLENDMODE(flags)); + m_renderer = renderer; + m_hash = texture_compute_hash(texsource, flags); + m_flags = flags; + m_texinfo = texsource; + m_texinfo.seqid = -1; // force set data + m_is_rotated = FALSE; + m_setup = setup; + m_sdl_blendmode = map_blendmode(PRIMFLAG_GET_BLENDMODE(flags)); + m_pitch = 0; switch (PRIMFLAG_GET_TEXFORMAT(flags)) { case TEXFORMAT_ARGB32: - texture->format = SDL_TEXFORMAT_ARGB32; + m_format = SDL_TEXFORMAT_ARGB32; break; case TEXFORMAT_RGB32: - texture->format = texsource->palette() ? SDL_TEXFORMAT_RGB32_PALETTED : SDL_TEXFORMAT_RGB32; + m_format = texsource.palette() ? SDL_TEXFORMAT_RGB32_PALETTED : SDL_TEXFORMAT_RGB32; break; case TEXFORMAT_PALETTE16: - texture->format = SDL_TEXFORMAT_PALETTE16; + m_format = SDL_TEXFORMAT_PALETTE16; break; case TEXFORMAT_PALETTEA16: - texture->format = SDL_TEXFORMAT_PALETTE16A; + m_format = SDL_TEXFORMAT_PALETTE16A; break; case TEXFORMAT_YUY16: - texture->format = texsource->palette() ? SDL_TEXFORMAT_YUY16_PALETTED : SDL_TEXFORMAT_YUY16; + m_format = texsource.palette() ? SDL_TEXFORMAT_YUY16_PALETTED : SDL_TEXFORMAT_YUY16; break; default: osd_printf_error("Unknown textureformat %d\n", PRIMFLAG_GET_TEXFORMAT(flags)); } - texture->rawwidth = texsource->width; - texture->rawheight = texsource->height; - if (setup->rotwidth != texture->rawwidth || setup->rotheight != texture->rawheight - || setup->dudx < 0 ) - texture->is_rotated = TRUE; + if (setup.rotwidth != m_texinfo.width || setup.rotheight != m_texinfo.height + || setup.dudx < 0 || setup.dvdy < 0) + m_is_rotated = TRUE; else - texture->is_rotated = FALSE; + m_is_rotated = FALSE; - //texture->sdl_access = SDL_TEXTUREACCESS_STATIC; - texture->sdl_access = SDL_TEXTUREACCESS_STREAMING; + //m_sdl_access = SDL_TEXTUREACCESS_STATIC; + m_sdl_access = SDL_TEXTUREACCESS_STREAMING; // Watch out for 0x0 textures ... - if (!texture->setup.rotwidth || !texture->setup.rotheight) + if (!m_setup.rotwidth || !m_setup.rotheight) osd_printf_warning("Trying to create texture with zero dim\n"); - // compute the size - texture->copyinfo = texture_compute_size_type(sdl->sdl_renderer, texsource, texture, flags); + // set copy_info + + m_copyinfo = compute_size_type(); - texture->texture_id = SDL_CreateTexture(sdl->sdl_renderer, texture->copyinfo->dst_fmt, texture->sdl_access, - texture->setup.rotwidth, texture->setup.rotheight); + m_texture_id = SDL_CreateTexture(m_renderer, m_copyinfo->dst_fmt, m_sdl_access, + m_setup.rotwidth, m_setup.rotheight); - if (!texture->texture_id) - osd_printf_error("Error creating texture: %d x %d, pixelformat %s error: %s\n", texture->setup.rotwidth, texture->setup.rotheight, - texture->copyinfo->dstname, SDL_GetError()); + if (!m_texture_id) + osd_printf_error("Error creating texture: %d x %d, pixelformat %s error: %s\n", m_setup.rotwidth, m_setup.rotheight, + m_copyinfo->dstname, SDL_GetError()); - if ( (texture->copyinfo->func != NULL) && (texture->sdl_access == SDL_TEXTUREACCESS_STATIC)) + if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) { - texture->pixels = malloc(texture->setup.rotwidth * texture->setup.rotheight * texture->copyinfo->dst_bpp); - texture->pixels_own=TRUE; + if (m_copyinfo->func != NULL) + m_pixels = malloc(m_setup.rotwidth * m_setup.rotheight * m_copyinfo->dst_bpp); + else + m_pixels = NULL; } - /* add us to the texture list */ - texture->next = sdl->texlist; - sdl->texlist = texture; + m_last_access = osd_ticks(); - texture->last_access = osd_ticks(); +} - return texture; +texture_info::~texture_info() +{ + SDL_DestroyTexture(m_texture_id); + if ( is_pixels_owned() && m_pixels != NULL ) + free(m_pixels); } //============================================================ // texture_set_data //============================================================ -static void texture_set_data(sdl_info *sdl, texture_info *texture, const render_texinfo *texsource, UINT32 flags) +void texture_info::set_data(const render_texinfo &texsource, const UINT32 flags) { - texture->copyinfo->time -= osd_ticks(); - if (texture->sdl_access == SDL_TEXTUREACCESS_STATIC) + m_copyinfo->time -= osd_ticks(); + if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) { - if ( texture->copyinfo->func ) + if ( m_copyinfo->func ) { - texture->pitch = texture->setup.rotwidth * texture->copyinfo->dst_bpp; - texture->copyinfo->func(texture, texsource); + m_pitch = m_setup.rotwidth * m_copyinfo->dst_bpp; + m_copyinfo->func(this, &texsource); } else { - texture->pixels = texsource->base; - texture->pitch = texture->texinfo.rowpixels * texture->copyinfo->dst_bpp; + m_pixels = texsource.base; + m_pitch = m_texinfo.rowpixels * m_copyinfo->dst_bpp; } - SDL_UpdateTexture(texture->texture_id, NULL, texture->pixels, texture->pitch); + SDL_UpdateTexture(m_texture_id, NULL, m_pixels, m_pitch); } else { - SDL_LockTexture(texture->texture_id, NULL, (void **) &texture->pixels, &texture->pitch); - if ( texture->copyinfo->func ) - texture->copyinfo->func(texture, texsource); + SDL_LockTexture(m_texture_id, NULL, (void **) &m_pixels, &m_pitch); + if ( m_copyinfo->func ) + m_copyinfo->func(this, &texsource); else { - UINT8 *src = (UINT8 *) texsource->base; - UINT8 *dst = (UINT8 *) texture->pixels; - int spitch = texsource->rowpixels * texture->copyinfo->dst_bpp; - int num = texsource->width * texture->copyinfo->dst_bpp; - int h = texsource->height; + UINT8 *src = (UINT8 *) texsource.base; + UINT8 *dst = (UINT8 *) m_pixels; + int spitch = texsource.rowpixels * m_copyinfo->dst_bpp; + int num = texsource.width * m_copyinfo->dst_bpp; + int h = texsource.height; while (h--) { memcpy(dst, src, num); src += spitch; - dst += texture->pitch; + dst += m_pitch; } } - SDL_UnlockTexture(texture->texture_id); + SDL_UnlockTexture(m_texture_id); } - texture->copyinfo->time += osd_ticks(); + m_copyinfo->time += osd_ticks(); } //============================================================ // compute rotation setup //============================================================ -static void compute_setup(sdl_info *sdl, const render_primitive *prim, quad_setup_data *setup, int flags) +void quad_setup_data::compute(const render_primitive &prim) { - const render_quad_texuv *texcoords = &prim->texcoords; - int texwidth = prim->texture.width; - int texheight = prim->texture.height; + const render_quad_texuv *texcoords = &prim.texcoords; + int texwidth = prim.texture.width; + int texheight = prim.texture.height; float fdudx, fdvdx, fdudy, fdvdy; float width, height; float fscale; /* determine U/V deltas */ - if ((PRIMFLAG_GET_SCREENTEX(flags))) + if ((PRIMFLAG_GET_SCREENTEX(prim.flags))) fscale = (float) video_config.prescale; else fscale = 1.0f; @@ -1032,25 +1059,31 @@ static void compute_setup(sdl_info *sdl, const render_primitive *prim, quad_setu fdudy = (texcoords->bl.u - texcoords->tl.u) / fscale; // b a12 fdvdy = (texcoords->bl.v - texcoords->tl.v) / fscale; // d a22 +#if 0 + printf("tl.u %f tl.v %f\n", texcoords->tl.u, texcoords->tl.v); + printf("tr.u %f tr.v %f\n", texcoords->tr.u, texcoords->tr.v); + printf("bl.u %f bl.v %f\n", texcoords->bl.u, texcoords->bl.v); + printf("br.u %f br.v %f\n", texcoords->br.u, texcoords->br.v); /* compute start and delta U,V coordinates now */ +#endif - setup->dudx = round_nearest(65536.0f * fdudx); - setup->dvdx = round_nearest(65536.0f * fdvdx); - setup->dudy = round_nearest(65536.0f * fdudy); - setup->dvdy = round_nearest(65536.0f * fdvdy); - setup->startu = round_nearest(65536.0f * (float) texwidth * texcoords->tl.u); - setup->startv = round_nearest(65536.0f * (float) texheight * texcoords->tl.v); + dudx = round_nearest(65536.0f * fdudx); + dvdx = round_nearest(65536.0f * fdvdx); + dudy = round_nearest(65536.0f * fdudy); + dvdy = round_nearest(65536.0f * fdvdy); + startu = round_nearest(65536.0f * (float) texwidth * texcoords->tl.u); + startv = round_nearest(65536.0f * (float) texheight * texcoords->tl.v); /* clamp to integers */ width = fabs((fdudx * (float) (texwidth) + fdvdx * (float) (texheight)) * fscale * fscale); height = fabs((fdudy * (float)(texwidth) + fdvdy * (float) (texheight)) * fscale * fscale); - setup->rotwidth = width; - setup->rotheight = height; + rotwidth = width; + rotheight = height; - setup->startu += (setup->dudx + setup->dudy) / 2; - setup->startv += (setup->dvdx + setup->dvdy) / 2; + startu += (dudx + dudy) / 2; + startv += (dvdx + dvdy) / 2; } @@ -1058,50 +1091,33 @@ static void compute_setup(sdl_info *sdl, const render_primitive *prim, quad_setu // texture_find //============================================================ -static texture_info *texture_find(sdl_info *sdl, const render_primitive *prim, quad_setup_data *setup) +texture_info *sdl_info::texture_find(const render_primitive &prim, const quad_setup_data &setup) { - HashT texhash = texture_compute_hash(&prim->texture, prim->flags); + HashT texhash = texture_compute_hash(prim.texture, prim.flags); texture_info *texture; osd_ticks_t now = osd_ticks(); // find a match - for (texture = sdl->texlist; texture != NULL; ) - if (texture->hash == texhash && - texture->texinfo.base == prim->texture.base && - texture->texinfo.width == prim->texture.width && - texture->texinfo.height == prim->texture.height && - texture->texinfo.rowpixels == prim->texture.rowpixels && - texture->setup.dudx == setup->dudx && - texture->setup.dvdx == setup->dvdx && - texture->setup.dudy == setup->dudy && - texture->setup.dvdy == setup->dvdy && - ((texture->flags ^ prim->flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0) + for (texture = m_texlist.first(); texture != NULL; ) + if (texture->hash() == texhash && + texture->matches(prim, setup)) { - /* would we choose another blitter ? */ - if ((texture->copyinfo->samples & 0x1f) == 0x1f) + /* would we choose another blitter based on performance ? */ + if ((texture->m_copyinfo->samples & 0x7f) == 0x7f) { - if (texture->copyinfo != texture_compute_size_type(sdl->sdl_renderer, &texture->texinfo, texture, prim->flags)) + if (texture->m_copyinfo != texture->compute_size_type()) return NULL; -#if 0 - else - { - /* reset stats */ - texture->copyinfo->samples = 0; - texture->copyinfo->time = 0; - texture->copyinfo->pixel_count = 0; - } -#endif } - texture->last_access = now; + texture->m_last_access = now; return texture; } else { /* free resources not needed any longer? */ texture_info *expire = texture; - texture = texture->next; - if (now - expire->last_access > osd_ticks_per_second()) - drawsdl2_destroy_texture(sdl, expire); + texture = texture->next(); + if (now - expire->m_last_access > osd_ticks_per_second()) + m_texlist.remove(*expire); } // nothing found @@ -1112,81 +1128,51 @@ static texture_info *texture_find(sdl_info *sdl, const render_primitive *prim, q // texture_update //============================================================ -static texture_info * texture_update(sdl_window_info *window, const render_primitive *prim) +texture_info * sdl_info::texture_update(const render_primitive &prim) { - sdl_info *sdl = (sdl_info *) window->dxdata; quad_setup_data setup; texture_info *texture; - compute_setup(sdl, prim, &setup, prim->flags); + setup.compute(prim); - texture = texture_find(sdl, prim, &setup); + texture = texture_find(prim, setup); // if we didn't find one, create a new texture - if (texture == NULL && prim->texture.base != NULL) + if (texture == NULL && prim.texture.base != NULL) { - texture = texture_create(window, &prim->texture, &setup, prim->flags); + texture = global_alloc(texture_info(m_renderer, prim.texture, setup, prim.flags)); + /* add us to the texture list */ + m_texlist.prepend(*texture); + } if (texture != NULL) { - if (prim->texture.base != NULL && texture->texinfo.seqid != prim->texture.seqid) + if (prim.texture.base != NULL && texture->texinfo().seqid != prim.texture.seqid) { - texture->texinfo.seqid = prim->texture.seqid; + texture->texinfo().seqid = prim.texture.seqid; // if we found it, but with a different seqid, copy the data - texture_set_data(sdl, texture, &prim->texture, prim->flags); + texture->set_data(prim.texture, prim.flags); } } return texture; } -static void drawsdl2_destroy_texture(sdl_info *sdl, texture_info *texture) -{ - texture_info *p; - - SDL_DestroyTexture(texture->texture_id); - if ( texture->pixels_own ) - { - free(texture->pixels); - texture->pixels=NULL; - texture->pixels_own=FALSE; - } - - for (p=sdl->texlist; p != NULL; p = p->next) - if (p->next == texture) - break; - if (p == NULL) - sdl->texlist = NULL; - else - p->next = texture->next; - global_free(texture); -} static void drawsdl2_destroy_all_textures(sdl_window_info *window) { sdl_info *sdl = (sdl_info *) window->dxdata; - texture_info *next_texture=NULL, *texture = NULL; - int lock=FALSE; if (sdl == NULL) return; if(window->primlist) { - lock=TRUE; window->primlist->acquire_lock(); + sdl->m_texlist.reset(); + window->primlist->release_lock(); } - - texture = sdl->texlist; - - while (texture) - { - next_texture = texture->next; - drawsdl2_destroy_texture(sdl, texture); - texture = next_texture; - } - - if (lock) - window->primlist->release_lock(); + else + sdl->m_texlist.reset(); } -- cgit v1.2.3