Changeset 1992


Ignore:
Timestamp:
Oct 9, 2012, 1:15:56 AM (11 years ago)
Author:
sam
Message:

gpu: allow to specify the pixel format when creating a texture; the
internal format is then automatically deduced. Only a few 8-bit RGB
or RGBA formats are supported for now.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gpu/texture.cpp

    r1991 r1992  
    4343
    4444    ivec2 m_size;
     45    PixelFormat m_format;
    4546
    4647#if defined USE_D3D9
     
    5051#else
    5152    GLuint m_texid;
     53    GLint m_internal_format;
     54    GLenum m_gl_format, m_gl_type;
    5255#endif
    5356};
     
    5861//
    5962
    60 /* FIXME: this is all hardcoded over the place */
     63#define GET_CLAMPED(array, index) \
     64    array[std::max(0, std::min((int)(index), \
     65                   (int)sizeof(array) / (int)sizeof(*array)))]
     66
     67Texture::Texture(ivec2 size, PixelFormat format)
     68  : m_data(new TextureData)
     69{
     70    m_data->m_size = size;
     71    m_data->m_format = format;
     72
     73#if defined USE_D3D9 || defined _XBOX
     74    static int const d3d_formats[] =
     75    {
     76        /* Unknown */
     77        D3DFMT_UNKNOWN,
     78
     79        /* R8G8B8 */
     80        D3DFMT_R8G8B8,
     81
     82        /* A8R8G8B8 */
     83#   if defined USE_D3D9
     84        D3DFMT_A8R8G8B8,
     85#   else
     86        /* By default the X360 will swizzle the texture. Ask for linear. */
     87        D3DFMT_LIN_A8R8G8B8,
     88#   endif
     89    };
     90
     91    int d3d_format = GET_CLAMPED(d3d_formats, format);
     92#   if defined USE_D3D9
     93    int d3d_usage = D3DUSAGE_DYNAMIC;
     94#   else
     95    int d3d_usage = D3DUSAGE_WRITEONLY;
     96#   endif
     97
     98    g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
     99                               d3d_usage, d3d_format,
     100                               D3DPOOL_DEFAULT, &m_data->m_tex, NULL);
     101#else
     102    static struct
     103    {
     104        GLint internal_format;
     105        GLenum format, type;
     106    }
     107    const gl_formats[] =
     108    {
     109        /* Unknown */
     110        { 0, 0, 0 },
     111
     112        /* R8G8B8 */
     113        { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE },
     114
     115        /* A8R8G8B8 */
    61116#if __CELLOS_LV2__
    62 static GLint const INTERNAL_FORMAT = GL_ARGB_SCE;
    63 static GLenum const TEXTURE_FORMAT = GL_BGRA;
    64 static GLenum const TEXTURE_TYPE = GL_UNSIGNED_INT_8_8_8_8_REV;
     117        { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
    65118#elif defined __native_client__ || defined HAVE_GLES_2X
    66 static GLint const INTERNAL_FORMAT = GL_RGBA;
    67 static GLenum const TEXTURE_FORMAT = GL_RGBA;
    68 static GLenum const TEXTURE_TYPE = GL_UNSIGNED_BYTE;
    69 #elif !defined USE_D3D9 && !defined _XBOX
    70 /* Seems efficient for little endian textures */
    71 static GLint const INTERNAL_FORMAT = GL_RGBA;
    72 static GLenum const TEXTURE_FORMAT = GL_BGRA;
    73 static GLenum const TEXTURE_TYPE = GL_UNSIGNED_INT_8_8_8_8_REV;
    74 #endif
    75 
    76 Texture::Texture(ivec2 size)
    77   : m_data(new TextureData)
    78 {
    79     m_data->m_size = size;
    80 
    81 #if defined USE_D3D9
    82     g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
    83                                D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8,
    84                                D3DPOOL_DEFAULT, &m_data->m_tex, NULL);
    85 #elif defined _XBOX
    86     /* By default the X360 will swizzle the texture. Ask for linear. */
    87     g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
    88                                D3DUSAGE_WRITEONLY, D3DFMT_LIN_A8R8G8B8,
    89                                D3DPOOL_DEFAULT, &m_data->m_tex, NULL);
    90 #else
     119        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
     120#else
     121        /* Seems efficient for little endian textures */
     122        { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV },
     123#endif
     124
     125        /* A8B8G8R8 */
     126#if __CELLOS_LV2__
     127        { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
     128#elif defined __native_client__ || defined HAVE_GLES_2X
     129        /* FIXME: if GL_RGBA is not available, we should advertise
     130         * this format as "not available" on this platform. */
     131        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
     132#else
     133        /* Seems efficient for little endian textures */
     134        { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
     135#endif
     136    };
     137
     138    m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
     139    m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
     140    m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
     141
    91142    glGenTextures(1, &m_data->m_texid);
    92143    glBindTexture(GL_TEXTURE_2D, m_data->m_texid);
     
    130181
    131182#else
    132     glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT,
     183    glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
    133184                 m_data->m_size.x, m_data->m_size.y, 0,
    134                  TEXTURE_FORMAT, TEXTURE_TYPE, data);
     185                 m_data->m_gl_format, m_data->m_gl_type, data);
    135186#endif
    136187}
     
    154205#else
    155206    glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
    156                     TEXTURE_FORMAT, TEXTURE_TYPE, data);
     207                    m_data->m_gl_format, m_data->m_gl_type, data);
    157208#endif
    158209}
  • trunk/src/gpu/texture.h

    r1987 r1992  
    2020{
    2121
     22struct PixelFormat
     23{
     24    /* XXX: make sure to update texture.cpp when this changes */
     25    enum Value
     26    {
     27        Unknown = 0,
     28        R8G8B8,
     29        A8R8G8B8,
     30        A8B8G8R8,
     31    }
     32    m_value;
     33
     34    inline PixelFormat() : m_value(Unknown) {}
     35    inline PixelFormat(Value v) : m_value(v) {}
     36    inline operator Value() { return m_value; }
     37};
     38
    2239class Texture
    2340{
    2441public:
    25     Texture(ivec2 size);
     42    Texture(ivec2 size, PixelFormat format);
    2643    ~Texture();
    2744
  • trunk/src/tileset.cpp

    r1952 r1992  
    5757
    5858    Image *img;
    59 #if defined USE_D3D9
    60     IDirect3DTexture9 *m_tex;
    61 #elif defined _XBOX
    62     D3DTexture *m_tex;
    63 #else
    64     GLuint m_tex;
    65 #endif
     59    Texture *m_texture;
    6660};
    6761
     
    7872
    7973    data->tiles = NULL;
    80     data->m_tex = 0;
     74    data->m_texture = 0;
    8175    data->img = new Image(path);
    8276    data->isize = data->img->GetSize();
     
    120114            delete data->img;
    121115        else
    122 #if defined USE_D3D9 || defined _XBOX
    123             /* FIXME: is it really the correct call? */
    124             data->m_tex->Release();
    125 #else
    126             glDeleteTextures(1, &data->m_tex);
    127 #endif
     116            delete data->m_texture;
    128117    }
    129118    else if (data->img)
    130119    {
    131 #if defined USE_D3D9 || defined _XBOX
    132         D3DFORMAT format;
    133 #else
    134         GLuint format;
    135 #endif
    136120        int planes;
     121        PixelFormat format = PixelFormat::Unknown;
    137122
    138123        switch (data->img->GetFormat())
    139124        {
    140125        case Image::FORMAT_RGB:
    141 #if defined USE_D3D9
    142            format = D3DFMT_R8G8B8;
    143 #elif defined _XBOX
    144            format = D3DFMT_LIN_A8R8G8B8; /* FIXME */
    145 #else
    146            format = GL_RGB;
    147 #endif
    148            planes = 3;
    149            break;
     126            format = PixelFormat::R8G8B8;
     127            planes = 3;
     128            break;
    150129        case Image::FORMAT_RGBA:
    151130        default:
    152 #if defined USE_D3D9
    153            format = D3DFMT_A8R8G8B8;
    154 #elif defined _XBOX
    155             /* By default the X360 will swizzle the texture. Ask for linear. */
    156            format = D3DFMT_LIN_A8R8G8B8;
    157 #else
    158            format = GL_RGBA;
    159 #endif
    160            planes = 4;
    161            break;
     131            format = PixelFormat::A8R8G8B8;
     132            planes = 4;
     133            break;
    162134        }
    163135
     
    176148        }
    177149
    178 #if defined USE_D3D9 || defined _XBOX
    179         D3DLOCKED_RECT rect;
    180         HRESULT hr;
    181 #   if defined USE_D3D9
    182         hr = g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_DYNAMIC, format,
    183                                         D3DPOOL_DEFAULT, &data->m_tex, NULL);
    184 #   elif defined _XBOX
    185         hr = g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_WRITEONLY, format,
    186                                         D3DPOOL_DEFAULT, &data->m_tex, NULL);
    187 #   endif
    188         if (FAILED(hr))
    189             Abort();
    190 #   if defined USE_D3D9
    191         hr = data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
    192 #   else
    193         hr = data->m_tex->LockRect(0, &rect, NULL, 0);
    194 #   endif
    195         if (FAILED(hr))
    196             Abort();
    197         for (int j = 0; j < h; j++)
    198             memcpy((uint8_t *)rect.pBits + j * rect.Pitch, pixels + w * j * 4, w * 4);
    199         hr = data->m_tex->UnlockRect(0);
    200         if (FAILED(hr))
    201             Abort();
    202 #else
    203         glGenTextures(1, &data->m_tex);
    204         glEnable(GL_TEXTURE_2D);
    205         glBindTexture(GL_TEXTURE_2D, data->m_tex);
    206 
    207         glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
    208                      format, GL_UNSIGNED_BYTE, pixels);
    209 
    210         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    211         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    212 #endif
     150        data->m_texture = new Texture(ivec2(w, h), format);
     151        data->m_texture->SetData(pixels);
    213152
    214153        if (pixels != data->img->GetData())
     
    238177void TileSet::Bind()
    239178{
    240     if (!data->img && data->m_tex)
    241     {
    242 #if defined USE_D3D9 || defined _XBOX
    243         HRESULT hr = g_d3ddevice->SetTexture(0, data->m_tex);
    244         if (FAILED(hr))
    245             Abort();
    246 #else
    247         glActiveTexture(GL_TEXTURE0);
    248         glBindTexture(GL_TEXTURE_2D, data->m_tex);
    249 #endif
    250     }
     179    if (!data->img && data->m_texture)
     180        data->m_texture->Bind();
    251181}
    252182
    253183void TileSet::Unbind()
    254184{
    255     if (!data->img && data->m_tex)
    256     {
    257 #if defined USE_D3D9 || defined _XBOX
    258         HRESULT hr = g_d3ddevice->SetTexture(0, NULL);
    259         if (FAILED(hr))
    260             Abort();
    261 #else
    262         glActiveTexture(GL_TEXTURE0);
    263         glBindTexture(GL_TEXTURE_2D, 0);
    264 #endif
    265     }
     185    ;
    266186}
    267187
     
    288208    }
    289209
    290     if (!data->img && data->m_tex)
     210    if (!data->img && data->m_texture)
    291211    {
    292212        float tmp[10];
  • trunk/tutorial/11_fractal.cpp

    r1988 r1992  
    446446            /* Create a texture of half the width and twice the height
    447447             * so that we can upload four different subimages each frame. */
    448             m_texture = new Texture(ivec2(m_size.x / 2, m_size.y * 2));
     448            m_texture = new Texture(ivec2(m_size.x / 2, m_size.y * 2),
     449                                    PixelFormat::A8B8G8R8);
    449450
    450451            /* Ensure the texture data is complete at least once, otherwise
Note: See TracChangeset for help on using the changeset viewer.