Ticket #935: SDL2_color_cursors_wip.patch

File SDL2_color_cursors_wip.patch, 4.7 KB (added by historic_bruno, 11 years ago)

WIP patch to test SDL 2.0 color hw cursors

  • source/lib/res/graphics/cursor.cpp

     
    1 /* Copyright (c) 2012 Wildfire Games
     1/* Copyright (c) 2013 Wildfire Games
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
    44 * a copy of this software and associated documentation files (the
     
    3131#include <cstdio>
    3232#include <sstream>
    3333
     34#include "lib/external_libraries/libsdl.h"
    3435#include "lib/ogl.h"
    3536#include "lib/sysdep/cursor.h"
    3637#include "ogl_tex.h"
     
    7677}
    7778
    7879
     80class SDLCursor
     81{
     82    SDL_Surface* surface;
     83    SDL_Cursor* cursor;
     84
     85public:
     86    Status create(const PIVFS& vfs, const VfsPath& pathname, int hotspotx_, int hotspoty_)
     87    {
     88        shared_ptr<u8> file; size_t fileSize;
     89        RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, file, fileSize));
     90
     91        ScopedTex t;
     92        RETURN_STATUS_IF_ERR(tex_decode(file, fileSize, &t));
     93
     94        // convert to required BGRA format.
     95        const size_t flags = (t.flags | TEX_BGR) & ~TEX_DXT;
     96        RETURN_STATUS_IF_ERR(tex_transform_to(&t, flags));
     97        void* bgra_img = tex_get_data(&t);
     98        if(!bgra_img)
     99            WARN_RETURN(ERR::FAIL);
     100
     101        surface = SDL_CreateRGBSurfaceFrom(bgra_img, (int)t.w, (int)t.h, 32, (int)t.w*4, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
     102        if (!surface)
     103            return ERR::FAIL;
     104        cursor = SDL_CreateColorCursor(surface, hotspotx_, hotspoty_);
     105        if (!cursor)
     106            return ERR::FAIL;
     107
     108        return INFO::OK;
     109    }
     110
     111    void set()
     112    {
     113        SDL_SetCursor(cursor);
     114    }
     115
     116    void destroy()
     117    {
     118        SDL_FreeCursor(cursor);
     119        SDL_FreeSurface(surface);
     120    }
     121};
     122
    79123// no init is necessary because this is stored in struct Cursor, which
    80124// is 0-initialized by h_mgr.
    81125class GLCursor
     
    151195{
    152196    CK_Default,
    153197    CK_System,
     198    CK_SDL,
    154199    CK_OpenGL
    155200};
    156201
     
    164209    // valid iff kind == CK_System
    165210    sys_cursor system_cursor;
    166211
     212    // valid iff kind == CK_SDL
     213    SDLCursor sdl_cursor;
     214
    167215    // valid iff kind == CK_OpenGL
    168216    GLCursor gl_cursor;
    169217    sys_cursor gl_empty_system_cursor;
     
    187235        sys_cursor_free(c->system_cursor);
    188236        break;
    189237
     238    case CK_SDL:
     239        c->sdl_cursor.destroy();
     240        break;
     241
    190242    case CK_OpenGL:
    191243        c->gl_cursor.destroy();
     244#if !SDL_VERSION_ATLEAST(2, 0, 0)
    192245        sys_cursor_free(c->gl_empty_system_cursor);
     246#endif
    193247        break;
    194248
    195249    default:
     
    215269
    216270    const VfsPath pathnameImage = pathname.ChangeExtension(L".png");
    217271
    218     // try loading as system cursor (2d, hardware accelerated)
    219     if(!c->forceGL && load_sys_cursor(vfs, pathnameImage, hotspotx, hotspoty, &c->system_cursor) == INFO::OK)
    220         c->kind = CK_System;
     272    if(!c->forceGL)
     273    {
     274#if SDL_VERSION_ATLEAST(2, 0, 0)
     275        // try loading as SDL 2.0 cursor
     276        if (c->sdl_cursor.create(vfs, pathnameImage, hotspotx, hotspoty) == INFO::OK)
     277            c->kind = CK_SDL;
     278#else
     279        // try loading as system cursor (2d, hardware accelerated)
     280        if (load_sys_cursor(vfs, pathnameImage, hotspotx, hotspoty, &c->system_cursor) == INFO::OK)
     281            c->kind = CK_System;
     282#endif
     283    }
    221284    // fall back to GLCursor (system cursor code is disabled or failed)
    222285    else if(c->gl_cursor.create(vfs, pathnameImage, hotspotx, hotspoty) == INFO::OK)
    223286    {
    224287        c->kind = CK_OpenGL;
     288#if !SDL_VERSION_ATLEAST(2, 0, 0)
    225289        // (we need to hide the system cursor when using a OpenGL cursor)
    226290        sys_cursor_create_empty(&c->gl_empty_system_cursor);
     291#endif
    227292    }
    228293    // everything failed, leave cursor unchanged
    229294    else
     
    244309            WARN_RETURN(ERR::_1);
    245310        break;
    246311
     312    case CK_SDL:
     313        break;  // nothing to do
     314
    247315    case CK_OpenGL:
    248316        RETURN_STATUS_IF_ERR(c->gl_cursor.validate());
    249317        break;
     
    269337        type = L"sys";
    270338        break;
    271339
     340    case CK_SDL:
     341        type = L"sdl";
     342        break;
     343
    272344    case CK_OpenGL:
    273345        type = L"gl";
    274346        break;
     
    311383    // hide the cursor
    312384    if(!name)
    313385    {
     386#if !SDL_VERSION_ATLEAST(2, 0, 0)
    314387        sys_cursor_set(0);
     388#else
     389        SDL_ShowCursor(SDL_DISABLE);
     390#endif
    315391        return INFO::OK;
    316392    }
    317393
     
    331407    case CK_System:
    332408        sys_cursor_set(c->system_cursor);
    333409        break;
     410       
     411    case CK_SDL:
     412        c->sdl_cursor.set();
     413        SDL_ShowCursor(SDL_ENABLE);
     414        break;
    334415
    335416    case CK_OpenGL:
    336417        c->gl_cursor.draw(x, y);
     418#if !SDL_VERSION_ATLEAST(2, 0, 0)
    337419        // note: gl_empty_system_cursor can be 0 if sys_cursor_create_empty
    338420        // failed; in that case we don't want to sys_cursor_set because that
    339421        // would restore the default cursor (which is exactly what we're
    340422        // trying to avoid here)
    341423        if(c->gl_empty_system_cursor)
    342424            sys_cursor_set(c->gl_empty_system_cursor);
     425#else
     426        SDL_ShowCursor(SDL_DISABLE);
     427#endif
    343428        break;
    344429
    345430    default: