1
0
forked from 0ad/0ad

changed sys_cursor interface to load directly from file; can add createFromMemory version later if ever needed.

cursor: reflects the above; much simplified now.

ogl_tex: preserve all texture state across reloads. add quality
mechanism (perf boost on older cards). split up upload code. add
ogl_tex_transform(). add more docs.

renderer, GUIrenderer, unifont: bring in line with ogl_tex changes (int
-> uint and call setters before ogl_tex_upload)

GameSetup.cpp: add tex quality mechanism

This was SVN commit r2803.
This commit is contained in:
janwas 2005-09-29 05:00:20 +00:00
parent 14df805761
commit cd2f3948dd
9 changed files with 809 additions and 476 deletions

View File

@ -389,7 +389,9 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, CStr &SpriteName, CRect
return;
}
int err = ogl_tex_upload(h, GL_LINEAR);
(void)ogl_tex_set_filter(h, GL_LINEAR);
int err = ogl_tex_upload(h);
if (err < 0)
{
LOG(ERROR, LOG_CATEGORY, "Error uploading texture '%s': %d", (const char*)cit->m_TextureName, err);
@ -398,11 +400,11 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, CStr &SpriteName, CRect
Call.m_TexHandle = h;
int t_w = 0, t_h = 0;
uint t_w = 0, t_h = 0;
(void)ogl_tex_get_size(h, &t_w, &t_h, 0);
float TexWidth = t_w, TexHeight = t_h;
int flags = 0; // assume no alpha on failure
uint flags = 0; // assume no alpha on failure
(void)ogl_tex_get_format(h, &flags, 0);
Call.m_EnableBlending = (flags & TEX_ALPHA) != 0;

View File

@ -6,7 +6,7 @@
// On Windows, allow runtime choice between system cursors and OpenGL
// cursors (Windows = more responsive, OpenGL = more consistent with what
// the game sees)
#define USE_WINDOWS_CURSOR 1
#define ALLOW_SYS_CURSOR 1
#include "lib/ogl.h"
#include "sysdep/sysdep.h" // sys_cursor_*
@ -19,27 +19,32 @@
class GLCursor
{
Handle ht;
int w, h;
int hotspotx, hotspoty;
uint w, h;
uint hotspotx, hotspoty;
public:
void create(Handle ht_, int w_, int h_, int hotspotx_, int hotspoty_)
int create(const char* filename, uint hotspotx_, uint hotspoty_)
{
ht = ht_;
w = w_; h = h_;
ht = ogl_tex_load(filename);
RETURN_ERR(ht);
(void)ogl_tex_get_size(ht, &w, &h, 0);
hotspotx = hotspotx_; hotspoty = hotspoty_;
WARN_ERR(ogl_tex_upload(ht, GL_NEAREST));
(void)ogl_tex_set_filter(ht, GL_NEAREST);
(void)ogl_tex_upload(ht);
return 0;
}
void destroy()
{
WARN_ERR(ogl_tex_free(ht));
(void)ogl_tex_free(ht);
}
void draw(int x, int y)
void draw(uint x, uint y)
{
WARN_ERR(ogl_tex_bind(ht));
(void)ogl_tex_bind(ht);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
@ -85,46 +90,28 @@ static int Cursor_reload(Cursor* c, const char* name, Handle)
{
char filename[VFS_MAX_PATH];
// Load the .txt file containing the pixel offset of the cursor's
// hotspot (the bit of it that's drawn at (g_mouse_x,g_mouse_y) )
snprintf(filename, ARRAY_SIZE(filename), "art/textures/cursors/%s.txt", name);
int hotspotx = 0, hotspoty = 0;
// read pixel offset of the cursor's hotspot [the bit of it that's
// drawn at (g_mouse_x,g_mouse_y)] from file.
uint hotspotx = 0, hotspoty = 0;
{
snprintf(filename, ARRAY_SIZE(filename), "art/textures/cursors/%s.txt", name);
void* p; size_t size;
Handle hm = vfs_load(filename, p, size);
WARN_ERR(hm);
if(hm > 0)
{
std::stringstream s(std::string((const char*)p, size));
s >> hotspotx >> hotspoty;
WARN_ERR(mem_free_h(hm));
}
RETURN_ERR(hm);
std::stringstream s(std::string((const char*)p, size));
s >> hotspotx >> hotspoty;
(void)mem_free_h(hm);
}
// load actual cursor
snprintf(filename, ARRAY_SIZE(filename), "art/textures/cursors/%s.png", name);
Handle ht = ogl_tex_load(filename);
RETURN_ERR(ht);
int w = 0, h = 0, bpp = 0; // remain 0 on failure
GLenum gl_fmt = 0; // (caught below)
void* img = 0;
(void)ogl_tex_get_size(ht, &w, &h, &bpp);
(void)ogl_tex_get_format(ht, 0, &gl_fmt);
(void)ogl_tex_get_data(ht, &img);
#if USE_WINDOWS_CURSOR
// verify texture format (this isn't done in sys_cursor_create to
// avoid needing to pass gl_fmt and bpp; it assumes 32-bit RGBA).
if(bpp != 32 || gl_fmt != GL_RGBA)
debug_warn("Cursor_reload: invalid texture format");
else
WARN_ERR(sys_cursor_create(w, h, img, hotspotx, hotspoty, &c->sys_cursor));
// .. system cursor (2d, hardware accelerated)
#if ALLOW_SYS_CURSOR
WARN_ERR(sys_cursor_load(filename, hotspotx, hotspoty, &c->sys_cursor));
#endif
// if the system cursor code is disabled or failed, fall back to GLCursor.
// .. fall back to GLCursor (system cursor code is disabled or failed)
if(!c->sys_cursor)
c->gl_cursor.create(ht, w, h, hotspotx, hotspoty);
RETURN_ERR(c->gl_cursor.create(filename, hotspotx, hotspoty));
return 0;
}
@ -160,7 +147,7 @@ int cursor_draw(const char* name, int x, int y)
}
Handle hc = cursor_load(name);
RETURN_ERR(hc);
CHECK_ERR(hc);
H_DEREF(hc, Cursor, c);
if(c->sys_cursor)

File diff suppressed because it is too large Load Diff

View File

@ -32,15 +32,21 @@ It basically wraps tex.cpp's texture info in a resource object
reference counting, caching, hotloading and safe access.
Caching and Texture Instances
-----------------------------
Texture Parameters
------------------
Caching is both an advantage and drawback. When opening the same
texture twice without previously freeing it, a reference to the
first instance is returned. Therefore, be advised that concurrent use of the
same texture but with differing parameters (e.g. upload quality) followed by
a reload of the first instance will result in using the wrong parameters.
For background and rationale why this is acceptable, see struct OglTex.
OpenGL textures are conditioned on several parameters including
filter and wrap mode. These are typically set once when the texture is
created, but must survive reloads (1). To that end, all state (2) is
set via ogl_tex_set_* (instead of direct glTexParameter calls) and
re-applied after a reload.
(1) the purpose of hotloading is to permit artists to see their changes
in-game without having to restart the map. reloads where the
texture looks different due to changed state are useless.
(2) currently only filter and wrap mode. no other glTexParameter
settings are used ATM; if that changes, add to OglTexState.
Uploading to OpenGL
@ -51,15 +57,27 @@ Uploading to OpenGL
texture parameters and data from system memory to OpenGL
(and thereby usually video memory).
In so doing, choices are made as to filtering algorithm and the
texture's internal representation (how it is stored in vmem) -
in particular, the bit depth. This can trade performance
(more/less data to copy) for quality (fidelity to original).
In so doing, choices are made as to the texture's internal representation
(how it is stored in vmem) - in particular, the bit depth.
This can trade performance (more/less data to copy) for quality
(fidelity to original).
We provide a mechanism that applies defaults to all uploads unless
overrides are specified (for individual ogl_tex_upload calls).
This allows a global "quality" setting that can boost performance on
We provide a mechanism that applies defaults to all uploads;
this allows a global "quality" setting that can boost performance on
older graphics cards without requiring anything else to be changed.
Textures with specific quality needs can override this via
ogl_tex_set_* or ogl_tex_upload parameters.
Caching and Texture Instances
-----------------------------
Caching is both an advantage and drawback. When opening the same
texture twice without previously freeing it, a reference to the
first instance is returned. Therefore, be advised that concurrent use of the
same texture but with differing parameters (e.g. upload quality) followed by
a reload of the first instance will result in using the wrong parameters.
For background and rationale why this is acceptable, see struct OglTex.
Example Usage
@ -84,14 +102,15 @@ Handle hTexture = ogl_tex_load("filename.dds");
(void)ogl_tex_free(hTexture);
2) Advanced usage: wrap existing texture data and specify
filter/internal_format overrides.
2) Advanced usage: wrap existing texture data, override filter,
specify internal_format and use multitexturing.
Tex t;
const uint flags = 0; // image is plain RGB, default orientation
void* data = [pre-existing image]
(void)tex_wrap(w, h, 24, flags, data, &t);
Handle hCompositeAlphaMap = ogl_tex_wrap(&t, "(alpha map composite)");
(void)ogl_tex_upload(hCompositeAlphaMap, GL_LINEAR, GL_INTENSITY);
(void)ogl_tex_set_filter(hCompositeAlphaMap, GL_LINEAR);
(void)ogl_tex_upload(hCompositeAlphaMap, 0, GL_INTENSITY);
// (your responsibility! tex_wrap attaches a reference but it is
// removed by ogl_tex_upload.)
free(data);
@ -114,13 +133,52 @@ free(data);
#include "lib/ogl.h"
#include "tex.h"
// change default upload settings - these affect performance vs. quality.
// may be overridden for individual textures via ogl_tex_upload parameters.
// pass 0 to keep the current setting; defaults and legal values are:
// - filter: GL_LINEAR; any valid OpenGL minification filter
// - bpp : 32; 16 or 32 (this toggles between RGBA4 and RGBA8)
extern void ogl_tex_set_default_upload(GLint filter, uint bpp);
//
// quality mechanism
//
enum OglTexQualityFlags
{
// emphatically require full quality for this texture.
// (q_flags are invalid if this is set together with any other bit)
// rationale: the value 0 is used to indicate "use default flags" in
// ogl_tex_upload and ogl_tex_set_defaults, so this is the only
// way we can say "disregard default and do not reduce anything".
OGL_TEX_FULL_QUALITY = 0x20,
// store the texture at half the normal bit depth
// (4 bits per pixel component, as opposed to 8).
// this increases performance on older graphics cards due to
// decreased size in vmem. it has no effect on
// compressed textures because they have a fixed internal format.
OGL_TEX_HALF_BPP = 0x10,
// store the texture at half its original resolution.
// this increases performance on older graphics cards due to
// decreased size in vmem.
// this is useful for also reducing quality of compressed textures,
// which are not affected by OGL_TEX_HALF_BPP.
// currently only implemented for images that contain mipmaps
// (otherwise, we'd have to resample, which is slow).
// note: scaling down to 1/4, 1/8, .. is easily possible without
// extra work, so we leave some bits free for that.
OGL_TEX_HALF_RES = 0x01
};
// change default settings - these affect performance vs. quality.
// may be overridden for individual textures via parameter to
// ogl_tex_upload or ogl_tex_set_filter, respectively.
//
// pass 0 to keep the current setting; defaults and legal values are:
// - q_flags: OGL_TEX_FULL_QUALITY; combination of OglTexQualityFlags
// - filter: GL_LINEAR; any valid OpenGL minification filter
extern void ogl_tex_set_defaults(uint q_flags, GLint filter);
//
// open/close
//
// load and return a handle to the texture given in <fn>.
// for a list of supported formats, see tex.h's tex_load.
@ -142,27 +200,59 @@ extern Handle ogl_tex_wrap(Tex* t, const char* fn = 0, uint flags = 0);
extern int ogl_tex_free(Handle& ht);
// upload the texture to OpenGL. texture filter and [internal] format
// may be specified to override the global defaults (see below).
// side effects:
// - enables texturing on TMU 0 and binds the texture to it;
// - frees the texel data! see ogl_tex_get_data.
extern int ogl_tex_upload(Handle ht, GLint filter_override = 0, GLint internal_fmt_override = 0, GLenum format_override = 0);
//
// set texture parameters
//
// these must be called before uploading; this simplifies
// things and avoids calling glTexParameter twice.
// override default filter (as set above) for this texture.
// must be called before uploading (raises a warning if called afterwards).
// filter is as defined by OpenGL; it is applied for both minification and
// magnification (for rationale and details, see OglTexState)
extern int ogl_tex_set_filter(Handle ht, GLint filter);
// override default wrap mode (GL_REPEAT) for this texture.
// must be called before uploading (raises a warning if called afterwards).
// wrap is as defined by OpenGL and applies to both S and T coordinates
// (rationale: see OglTexState).
extern int ogl_tex_set_wrap(Handle ht, GLint wrap);
//
// upload
//
// bind the texture to the specified unit [number] in preparation for
// using it in rendering. assumes multitexturing is available.
// not necessary before calling ogl_tex_upload!
// side effects:
// - enables (or disables, if <ht> == 0) texturing on the given unit.
extern int ogl_tex_bind(Handle ht, GLenum unit = 0);
// upload the texture to OpenGL.
// if q_flags_ovr != 0, it overrides the default quality vs. perf. flags;
// if (int_)fmt_over != 0, it overrides the texture loader's decision.
// side effects:
// - enables texturing on TMU 0 and binds the texture to it;
// - frees the texel data! see ogl_tex_get_data.
extern int ogl_tex_upload(Handle ht, uint q_flags_override = 0,
GLint internal_fmt_override = 0, GLenum fmt_override = 0);
//
// return information about the texture
//
// retrieve texture dimensions and bits per pixel.
// all params are optional and filled if non-NULL.
extern int ogl_tex_get_size(Handle ht, int* w, int* h, int* bpp);
extern int ogl_tex_get_size(Handle ht, uint* w, uint* h, uint* bpp);
// retrieve Tex.flags and the corresponding OpenGL format.
// the latter is determined during ogl_tex_upload and is 0 before that.
// all params are optional and filled if non-NULL.
extern int ogl_tex_get_format(Handle ht, int* flags, GLenum* fmt);
extern int ogl_tex_get_format(Handle ht, uint* flags, GLenum* fmt);
// retrieve pointer to texel data.
//
@ -173,4 +263,13 @@ extern int ogl_tex_get_format(Handle ht, int* flags, GLenum* fmt);
// uploading it or read directly from OpenGL (discouraged).
extern int ogl_tex_get_data(Handle ht, void** p);
//
// misc
//
// apply the specified transforms (as in tex_transform) to the image.
// must be called before uploading (raises a warning if called afterwards).
extern int ogl_tex_transform(Handle ht, uint flags);
#endif // #ifndef OGL_TEX_H__

View File

@ -163,7 +163,16 @@ static int UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h))
if (ht <= 0)
return (int)ht;
ogl_tex_upload(ht, GL_NEAREST, GL_ALPHA8, GL_ALPHA);
// the GL format is chosen as LUMINANCE, but we want ALPHA.
/*/*
There doesn't seem to be much difference between ALPHA4 and ALPHA8.
I can't notice an increase/decrease in visual quality when quantising to 4-bit values,
and it's more space-efficient; but it'd need run-time conversion or 4-bit TGAs,
and the memory difference is probably insignificant [assuming only active fonts are cached,
and it doesn't keep in memory every font that's ever been displayed], so it's probably easiest to just use ALPHA8 always.
*/
(void)ogl_tex_set_filter(ht, GL_NEAREST);
ogl_tex_upload(ht, 0, GL_ALPHA8, GL_ALPHA);
f->ht = ht;

View File

@ -112,12 +112,19 @@ extern int clipboard_free(wchar_t* copy);
// note: these do not warn on error; that is left to the caller.
// creates a cursor from the given 32 bpp RGBA texture. hotspot (hx,hy) is
// the offset from its upper-left corner to the position where mouse clicks
// are registered.
// creates a cursor from the given 32 bpp texture (described by tex.h flags).
// hotspot (hx,hy) is the offset from its upper-left corner to the
// position where mouse clicks are registered.
// the cursor must be cursor_free-ed when no longer needed.
extern int sys_cursor_create(int w, int h, void* img, int hx, int hy,
void** cursor);
extern int sys_cursor_create(uint w, uint h, uint flags, void* img,
uint hx, uint hy, void** cursor);
// creates a cursor from the given texture file.
// hotspot (hx,hy) is the offset from its upper-left corner to the
// position where mouse clicks are registered.
// the cursor must be cursor_free-ed when no longer needed.
extern int sys_cursor_load(const char* filename,
uint hx, uint hy, void** cursor);
// replaces the current system cursor with the one indicated. need only be
// called once per cursor; pass 0 to restore the default.

View File

@ -26,6 +26,7 @@
#include "lib.h"
#include "posix.h"
#include "error_dialog.h"
#include "lib/res/graphics/tex.h"
#if MSC_VERSION
#pragma comment(lib, "shell32.lib") // for pick_directory SH* calls
@ -547,39 +548,29 @@ static HCURSOR HCURSOR_from_ptr(void* p)
}
// creates a cursor from the given 32 bpp RGBA texture. hotspot (hx,hy) is
// the offset from its upper-left corner to the position where mouse clicks
// are registered.
// creates a cursor from the given texture file.
// hotspot (hx,hy) is the offset from its upper-left corner to the
// position where mouse clicks are registered.
// the cursor must be cursor_free-ed when no longer needed.
int sys_cursor_create(int w, int h, void* img, int hx, int hy,
void** cursor)
int sys_cursor_load(const char* filename,
uint hx, uint hy, void** cursor)
{
*cursor = 0;
Tex t;
RETURN_ERR(tex_load(filename, &t));
uint w = t.w, h = t.h;
// convert to BGRA (required by BMP).
// don't do this in-place so we don't spoil someone else's
// use of the texture (however unlikely that may be).
void* img_bgra = malloc(w*h*4);
if(!img_bgra)
return ERR_NO_MEM;
const u8* src = (const u8*)img;
u8* dst = (u8*)img_bgra;
for(int i = 0; i < w*h; i++)
{
const u8 r = src[0], g = src[1], b = src[2], a = src[3];
dst[0] = b; dst[1] = g; dst[2] = r; dst[3] = a;
dst += 4;
src += 4;
}
img = img_bgra;
// convert to BGRA (required by CreateBitmap).
const uint transforms = (t.flags & TEX_BGR) ^ TEX_BGR;
RETURN_ERR(tex_transform(&t, transforms));
void* tex_bgra = tex_get_data(&t);
// MSDN says selecting this HBITMAP into a DC is slower since we use
// CreateBitmap; bpp/format must be checked against those of the DC.
// this is the simplest way and we don't care about slight performance
// differences because this is typically only called once.
HBITMAP hbmColour = CreateBitmap(w, h, 1, 32, img_bgra);
HBITMAP hbmColour = CreateBitmap(w, h, 1, 32, tex_bgra);
free(img_bgra);
tex_free(&t);
// CreateIconIndirect doesn't access it; we just need to pass
// an empty bitmap.
@ -607,6 +598,7 @@ int sys_cursor_create(int w, int h, void* img, int hx, int hy,
}
// replaces the current system cursor with the one indicated. need only be
// called once per cursor; pass 0 to restore the default.
int sys_cursor_set(void* cursor)

View File

@ -592,6 +592,65 @@ static void InitSDL()
}
static const uint SANE_TEX_QUALITY_DEFAULT = 5; // keep in sync with code
static void SetTextureQuality(uint quality)
{
uint q_flags;
GLint filter;
retry:
// keep this in sync with SANE_TEX_QUALITY_DEFAULT
switch(quality)
{
// worst quality
case 0:
q_flags = OGL_TEX_HALF_RES|OGL_TEX_HALF_BPP;
filter = GL_NEAREST;
break;
// [perf] add bilinear filtering
case 1:
q_flags = OGL_TEX_HALF_RES|OGL_TEX_HALF_BPP;
filter = GL_LINEAR;
break;
// [vmem] no longer reduce resolution
case 2:
q_flags = OGL_TEX_HALF_BPP;
filter = GL_LINEAR;
break;
// [vmem] add mipmaps
case 3:
q_flags = OGL_TEX_HALF_BPP;
filter = GL_NEAREST_MIPMAP_LINEAR;
break;
// [perf] better filtering
case 4:
q_flags = OGL_TEX_HALF_BPP;
filter = GL_LINEAR_MIPMAP_LINEAR;
break;
// [vmem] no longer reduce bpp
case SANE_TEX_QUALITY_DEFAULT:
q_flags = OGL_TEX_FULL_QUALITY;
filter = GL_LINEAR_MIPMAP_LINEAR;
break;
// [perf] add anisotropy
case 6:
// TODO: add anisotropic filtering
q_flags = OGL_TEX_FULL_QUALITY;
filter = GL_LINEAR_MIPMAP_LINEAR;
break;
// invalid
default:
debug_warn("SetTextureQuality: invalid quality");
quality = SANE_TEX_QUALITY_DEFAULT;
// careful: recursion doesn't work and we don't want to duplicate
// the "sane" default values.
goto retry;
}
ogl_tex_set_defaults(q_flags, filter);
}
void EndGame()
{
@ -793,14 +852,17 @@ void Init(int argc, char* argv[], bool setup_gfx, bool setup_gui)
if (setup_gfx)
{
MICROLOG(L"set vmode");
SDL_WM_SetCaption("0 A.D.", "0 A.D.");
MICROLOG(L"SetVideoMode");
if(SetVideoMode(g_xres, g_yres, 32, !windowed) < 0)
{
LOG(ERROR, LOG_CATEGORY, "Could not set %dx%d graphics mode: %s", g_xres, g_yres, SDL_GetError());
throw PSERROR_System_VmodeFailed();
}
SDL_WM_SetCaption("0 A.D.", "0 A.D.");
uint quality = SANE_TEX_QUALITY_DEFAULT; // TODO: set value from config file
SetTextureQuality(quality);
}
oglCheck();

View File

@ -42,15 +42,6 @@
#define LOG_CATEGORY "graphics"
/*
// jw: unused
static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data)
{
int err = tex_write(filename, width, height, bpp, TEX_BGR, data);
return (err == 0);
}
*/
///////////////////////////////////////////////////////////////////////////////////
// CRenderer destructor
CRenderer::CRenderer()
@ -86,7 +77,7 @@ CRenderer::CRenderer()
m_SWaterScrollCounter=0;
m_TWaterScrollCounter=0;
m_WaterCurrentTex=0;
for (int x=0; x<60; x++)
{
char waterName[1000];
@ -98,22 +89,7 @@ CRenderer::CRenderer()
ogl_tex_free(m_WaterTexture[x]);
}
else
{
int tw=0,th=0;
(void)ogl_tex_get_size(m_WaterTexture[x], &tw, &th, 0);
if(!is_pow2(tw) || !is_pow2(th))
{
LOG(ERROR, LOG_CATEGORY, "LoadTexture failed on \"%s\" : not a power of 2 texture",waterName);
ogl_tex_free(m_WaterTexture[x]);
}
else
{
ogl_tex_bind(m_WaterTexture[x]);
ogl_tex_upload(m_WaterTexture[x], GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
}
ogl_tex_upload(m_WaterTexture[x]);
}
}
@ -1194,40 +1170,38 @@ bool CRenderer::LoadTexture(CTexture* texture,u32 wrapflags)
const Handle errorhandle = -1;
Handle h=texture->GetHandle();
if (h) {
// already tried to load this texture, nothing to do here - just return success according
// to whether this is a valid handle or not
// already tried to load this texture
if (h)
{
// nothing to do here - just return success according to
// whether this is a valid handle or not
return h==errorhandle ? true : false;
} else {
h=ogl_tex_load(texture->GetName());
if (h <= 0) {
LOG(ERROR, LOG_CATEGORY, "LoadTexture failed on \"%s\"",(const char*) texture->GetName());
texture->SetHandle(errorhandle);
return false;
} else {
int tw=0,th=0;
(void)ogl_tex_get_size(h, &tw, &th, 0);
if(!is_pow2(tw) || !is_pow2(th)) {
LOG(ERROR, LOG_CATEGORY, "LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName());
ogl_tex_free(h);
texture->SetHandle(errorhandle);
return false;
} else {
ogl_tex_bind(h);
ogl_tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
if (wrapflags) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapflags);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
texture->SetHandle(h);
return true;
}
}
}
h=ogl_tex_load(texture->GetName());
if (h <= 0)
{
LOG(ERROR, LOG_CATEGORY, "LoadTexture failed on \"%s\"",(const char*) texture->GetName());
texture->SetHandle(errorhandle);
return false;
}
if(!wrapflags)
wrapflags = GL_CLAMP_TO_EDGE;
(void)ogl_tex_set_wrap(h, wrapflags);
(void)ogl_tex_set_filter(h, GL_LINEAR_MIPMAP_LINEAR);
// (this also verifies that the texture is a power-of-two)
if(ogl_tex_upload(h) < 0)
{
LOG(ERROR, LOG_CATEGORY, "LoadTexture failed on \"%s\" : upload failed",(const char*) texture->GetName());
ogl_tex_free(h);
texture->SetHandle(errorhandle);
return false;
}
texture->SetHandle(h);
return true;
}
@ -1277,7 +1251,7 @@ bool CRenderer::IsTextureTransparent(CTexture* texture)
if (!texture) return false;
Handle h=texture->GetHandle();
int flags = 0; // assume no alpha on failure
uint flags = 0; // assume no alpha on failure
(void)ogl_tex_get_format(h, &flags, 0);
return (flags & TEX_ALPHA) != 0;
}
@ -1319,11 +1293,11 @@ int CRenderer::LoadAlphaMaps()
"blendushape.png",
"blendbad.png"
};
int base = 0; // texture width/height (see below)
uint base = 0; // texture width/height (see below)
// for convenience, we require all alpha maps to be of the same BPP
// (avoids another ogl_tex_get_size call, and doesn't hurt)
int bpp = 0;
for(int i=0;i<NumAlphaMaps;i++)
uint bpp = 0;
for(uint i=0;i<NumAlphaMaps;i++)
{
(void)pp_append_file(&pp, fnames[i]);
textures[i] = ogl_tex_load(pp.path);
@ -1331,7 +1305,7 @@ int CRenderer::LoadAlphaMaps()
// get its size and make sure they are all equal.
// (the packing algo assumes this)
int this_width = 0, this_bpp = 0; // fail-safe
uint this_width = 0, this_bpp = 0; // fail-safe
(void)ogl_tex_get_size(textures[i], &this_width, 0, &this_bpp);
// .. first iteration: establish size
if(i == 0)
@ -1347,24 +1321,24 @@ int CRenderer::LoadAlphaMaps()
//
// copy each alpha map (tile) into one buffer, arrayed horizontally.
//
int tile_w = 2+base+2; // 2 pixel border (avoids bilinear filtering artifacts)
int total_w = RoundUpToPowerOf2(tile_w * NumAlphaMaps);
int total_h = base; debug_assert(is_pow2(total_h));
uint tile_w = 2+base+2; // 2 pixel border (avoids bilinear filtering artifacts)
uint total_w = RoundUpToPowerOf2(tile_w * NumAlphaMaps);
uint total_h = base; debug_assert(is_pow2(total_h));
u8* data=new u8[total_w*total_h*3];
// for each tile on row
for(int i=0;i<NumAlphaMaps;i++)
for(uint i=0;i<NumAlphaMaps;i++)
{
// get src of copy
const u8* src = 0;
(void)ogl_tex_get_data(textures[i], (void**)&src);
int srcstep=bpp/8;
uint srcstep=bpp/8;
// get destination of copy
u8* dst=data+3*(i*tile_w);
// for each row of image
for (int j=0;j<base;j++) {
for (uint j=0;j<base;j++) {
// duplicate first pixel
CopyTriple(dst,src);
dst+=3;
@ -1372,7 +1346,7 @@ int CRenderer::LoadAlphaMaps()
dst+=3;
// copy a row
for (int k=0;k<base;k++) {
for (uint k=0;k<base;k++) {
CopyTriple(dst,src);
dst+=3;
src+=srcstep;
@ -1393,17 +1367,16 @@ int CRenderer::LoadAlphaMaps()
m_AlphaMapCoords[i].v1=1.0f;
}
for (int i=0;i<NumAlphaMaps;i++)
for (uint i=0;i<NumAlphaMaps;i++)
ogl_tex_free(textures[i]);
// upload the composite texture
Tex t;
(void)tex_wrap(total_w, total_h, 24, 0, data, &t);
m_hCompositeAlphaMap = ogl_tex_wrap(&t, "(alpha map composite)");
(void)ogl_tex_upload(m_hCompositeAlphaMap, GL_LINEAR, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
oglSquelchError(GL_INVALID_ENUM); // GL_CLAMP_TO_EDGE
(void)ogl_tex_set_filter(m_hCompositeAlphaMap, GL_LINEAR);
(void)ogl_tex_set_wrap (m_hCompositeAlphaMap, GL_CLAMP_TO_EDGE);
(void)ogl_tex_upload(m_hCompositeAlphaMap, 0, GL_INTENSITY);
delete[] data;
return 0;