source: trunk/src/gpu/texture.cpp @ 2506

Last change on this file since 2506 was 2506, checked in by sam, 7 years ago

base: start removing occurrences of NULL on our long journey to nullptr.

  • Property svn:keywords set to Id
File size: 6.3 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include "core.h"
16#include "lolgl.h"
17
18#if defined _WIN32 && defined USE_D3D9
19#   define FAR
20#   define NEAR
21#   include <d3d9.h>
22#endif
23
24using namespace std;
25
26#if defined USE_D3D9
27extern IDirect3DDevice9 *g_d3ddevice;
28#elif defined _XBOX
29extern D3DDevice *g_d3ddevice;
30#endif
31
32namespace lol
33{
34
35//
36// The TextureData class
37// ---------------------
38//
39
40class TextureData
41{
42    friend class Texture;
43
44    ivec2 m_size;
45    PixelFormat m_format;
46
47#if defined USE_D3D9
48    IDirect3DTexture9 *m_texture;
49#elif defined _XBOX
50    D3DTexture *m_texture;
51#else
52    GLuint m_texture;
53    GLint m_internal_format;
54    GLenum m_gl_format, m_gl_type;
55#endif
56    int m_bytes_per_elem;
57};
58
59//
60// The Texture class
61// -----------------
62//
63
64#define GET_CLAMPED(array, index) \
65    array[std::max(0, std::min((int)(index), \
66                   (int)sizeof(array) / (int)sizeof(*array)))]
67
68Texture::Texture(ivec2 size, PixelFormat format)
69  : m_data(new TextureData)
70{
71    m_data->m_size = size;
72    m_data->m_format = format;
73
74#if defined USE_D3D9 || defined _XBOX
75    static struct
76    {
77        D3DFORMAT format;
78        int bytes;
79    }
80    const d3d_formats[] =
81    {
82        /* Unknown */
83        { D3DFMT_UNKNOWN, 0 },
84
85        /* R8G8B8 */
86#   if defined USE_D3D9
87        { D3DFMT_R8G8B8, 3 },
88#   else
89        { D3DFMT_UNKNOWN, 0 },
90#   endif
91
92        /* A8R8G8B8 */
93#   if defined USE_D3D9
94        { D3DFMT_A8R8G8B8, 4 },
95#   else
96        /* By default the X360 will swizzle the texture. Ask for linear. */
97        { D3DFMT_LIN_A8R8G8B8, 4 },
98#   endif
99
100        /* Y8 */
101#   if defined USE_D3D9
102        { D3DFMT_L8, 1 },
103#   else
104        /* By default the X360 will swizzle the texture. Ask for linear. */
105        { D3DFMT_LIN_L8, 1 },
106#   endif
107    };
108
109    D3DFORMAT d3d_format = GET_CLAMPED(d3d_formats, format).format;
110#   if defined USE_D3D9
111    int d3d_usage = D3DUSAGE_DYNAMIC;
112#   else
113    int d3d_usage = D3DUSAGE_WRITEONLY;
114#   endif
115
116    g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
117                               d3d_usage, d3d_format,
118                               D3DPOOL_DEFAULT, &m_data->m_texture, nullptr);
119    m_data->m_bytes_per_elem = GET_CLAMPED(d3d_formats, format).bytes;
120#else
121    static struct
122    {
123        GLint internal_format;
124        GLenum format, type;
125        int bytes;
126    }
127    const gl_formats[] =
128    {
129        { 0, 0, 0, 0 }, /* Unknown */
130
131#if __CELLOS_LV2__
132        { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 },
133        { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4 },
134        { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4 },
135        { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
136#elif defined __native_client__ || defined HAVE_GLES_2X
137        { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 3 },
138        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
139        /* FIXME: if GL_RGBA is not available, we should advertise
140         * this format as "not available" on this platform. */
141        { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
142        { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
143#else
144        { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 }, /* RGB_8 */
145        /* Seems efficient for little endian textures */
146        { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */
147        { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ABGR_8 */
148        { GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1 }, /* A8 */
149#endif
150    };
151
152    m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
153    m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
154    m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
155    m_data->m_bytes_per_elem = GET_CLAMPED(gl_formats, format).bytes;
156
157    glGenTextures(1, &m_data->m_texture);
158    glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
159
160#   if defined __CELLOS_LV2__
161    /* We need this hint because by default the storage type is
162     * GL_TEXTURE_SWIZZLED_GPU_SCE. */
163    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_ALLOCATION_HINT_SCE,
164                    GL_TEXTURE_TILED_GPU_SCE);
165#   endif
166    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
167    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
168#endif
169}
170
171ShaderTexture Texture::GetTexture() const
172{
173    ShaderTexture ret;
174#if defined USE_D3D9 || defined _XBOX
175    ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
176#else
177    ret.m_flags = m_data->m_texture;
178#endif
179    return ret;
180}
181
182void Texture::Bind()
183{
184#if defined _XBOX || defined USE_D3D9
185    g_d3ddevice->SetTexture(0, m_data->m_texture);
186#else
187#   if !defined HAVE_GLES_2X
188    glEnable(GL_TEXTURE_2D);
189#   endif
190    glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
191#endif
192}
193
194void Texture::SetData(void *data)
195{
196#if defined _XBOX || defined USE_D3D9
197    D3DLOCKED_RECT rect;
198#   if defined USE_D3D9
199    m_data->m_texture->LockRect(0, &rect, nullptr, D3DLOCK_DISCARD);
200#   else
201    m_data->m_texture->LockRect(0, &rect, nullptr, 0);
202#   endif
203
204    memcpy(rect.pBits, data, rect.Pitch * m_data->m_size.y);
205
206    m_data->m_texture->UnlockRect(0);
207
208#else
209    glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
210                 m_data->m_size.x, m_data->m_size.y, 0,
211                 m_data->m_gl_format, m_data->m_gl_type, data);
212#endif
213}
214
215void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
216{
217#if defined _XBOX || defined USE_D3D9
218    D3DLOCKED_RECT rect;
219    m_data->m_texture->LockRect(0, &rect, nullptr, 0);
220
221    int stride = size.x * m_data->m_bytes_per_elem;
222    for (int j = 0; j < size.y; j++)
223    {
224        uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch;
225        uint8_t *src = (uint8_t *)data + j * stride;
226        memcpy(dst, src, stride);
227    }
228
229    m_data->m_texture->UnlockRect(0);
230
231#else
232    glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
233                    m_data->m_gl_format, m_data->m_gl_type, data);
234#endif
235}
236
237Texture::~Texture()
238{
239#if defined USE_D3D9 || defined _XBOX
240    m_data->m_texture->Release();
241#else
242    glDeleteTextures(1, &m_data->m_texture);
243#endif
244
245    delete m_data;
246}
247
248} /* namespace lol */
249
Note: See TracBrowser for help on using the repository browser.