class DTexture | .h |
constructor | DTexture() Create a default texture object |
destructor | ~DTexture() |
SetSize | void SetSize(int w,int h) Sets texture size (wid/hgt); no object, just variables |
CreateTexture | void CreateTexture() Generate the texture and texture Object (name) and parameters in OpenGL Texture is created in the current OpenGL context (current canvas/gl) Note that the texture parameters are mostly selected from the D3 preferences. |
Flat functions |
glGetTexEnviv | int n; glGetTexEnviv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,&n); qdbg("DTexture:Create PRE; envmode=0x%x, MODULATE=%x, REPLACE=%x\n", n,GL_MODULATE,GL_REPLACE); } glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); |
glGetTexEnviv | int n; glGetTexEnviv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,&n); qdbg("DTexture:Create IN-bind; envmode=0x%x, MODULATE=%x, REPLACE=%x\n", n,GL_MODULATE,GL_REPLACE); } glBindTexture(GL_TEXTURE_2D,textureID); |
glGetTexEnviv | int n; glGetTexEnviv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,&n); qdbg("DTexture:Create POST-bind; envmode=0x%x, MODULATE=%x, REPLACE=%x\n", n,GL_MODULATE,GL_REPLACE); } #endif } |
class DTexture | .h |
Select | void Select() Select our texture (selects parameters as well/OpenGL) |
GetWidth | int GetWidth() Returns width of actual texture (may not match used part of texture) |
GetHeight | int GetHeight() Returns height of actual texture (may not match used part of texture) |
SetWrap | void SetWrap(int sWrap,int tWrap,int rWrap,int qWrap) Sets wrapping functions for the texture; default is to repeat the texture Possible values are CLAMP and REPEAT. OpenGL has more (CLAMP_TO_BORDER). Note: this function implicity selects the texture |
SetEnvMode | void SetEnvMode(int mode) Set environment mode. Possible values are: MODULATE, ADD, REPLACE See also 'man gltexenv' |
SetName | void SetName(cstring s) |
class DBitMapTexture | .h |
constructor | DBitMapTexture(QBitMap *ibm) : DTexture() Use an existing bitmap as a texture |
destructor | ~DBitMapTexture() |
class DDrawableTexture | .h |
constructor | DDrawableTexture(QDrawable *_draw) : DTexture() Create a texture for a drawable's contents |
destructor | ~DDrawableTexture() |
Refresh | void Refresh(bool front) |
class DMovieTexture | .h |
constructor | DMovieTexture(QMovie *mv) : DTexture() Create movie texture; render movie 'mv' into a pbuffer Note that the texture is rounded to 2**n size, so 720x576 becomes 1024x768 for the pbuffer size. |
destructor | ~DMovieTexture() Destroys pbuffer, DMbuffer, bufferpool |
Render | bool Render() Selects our pbuffer context and render the current frame into the pbuffer NOTES: - Turns off blending |
SetCurFrame | bool SetCurFrame(int frame) Sets current frame BUGS: - Currently does nothing; should set movie frame |
Advance | bool Advance() Shortcut to advance movie 1 frame. Returns TRUE if movie is still playing, FALSE if movie has ended |
/*
* DTexture - definition/implementation
* NOTES:
* - Some OpenGL calls are used which were *EXT in IRIX6.3
* - Generated by mkclass
* FUTURE:
* - Store and check OpenGL context when creating/selecting.
* These contexts must match, or else the texture was created
* in an other GLContext than it is being used.
* + Automatically switch to the right texture context? (warn!)
* (C) 19-02-1999 (18:10) MarketGraph/RVG
*/
#include <d3/texture.h>
#include <d3/global.h>
#include <qlib/app.h>
#include <qlib/error.h>
#include <qlib/opengl.h>
#include <qlib/dmvideoin.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <qlib/debug.h>
DEBUG_ENABLE
// If USE_ISTEXTURE_TEST is defined, every texture select will
// first test if the id really belongs to a texture.
// Ofcourse, this has performance impacts.
//#define USE_ISTEXTURE_TEST
#undef DBG_CLASS
#define DBG_CLASS "DTexture"
/*****************
* TEXTURE BASICS *
*****************/
DTexture::DTexture()
// Create a default texture object
{
DBG_C("ctor")
wid=hgt=0;
textureID=0;
gl=0;
}
DTexture::~DTexture()
{
DBG_C("dtor")
if(textureID)
glDeleteTextures(1,(GLuint*)&textureID);
}
void DTexture::SetSize(int w,int h)
// Sets texture size (wid/hgt); no object, just variables
{
if(wid!=0||hgt!=0)
{ qerr("DTexture::SetSize() called twice for the same object");
return;
}
wid=w; hgt=h;
}
void DTexture::CreateTexture()
// Generate the texture and texture Object (name) and parameters in OpenGL
// Texture is created in the current OpenGL context (current canvas/gl)
// Note that the texture parameters are mostly selected from
// the D3 preferences.
{
DBG_C("CreateTexture")
//static char pic[512*512*4]; int i;
//for(i=0;i<512*512*4;i++)pic[i]=rand();
// Remember GL context in which this texture 'lives'
gl=GetCurrentQGLContext();
// Create texture ID for this texture resource
glGenTextures(1,(GLuint*)&textureID);
glBindTexture(GL_TEXTURE_2D,textureID);
#ifndef WIN32
static bool fWarned;
// Very hard to trace problems occur when creating textures
// not in Q_BC (QCV). Warn for that, but don't overdo it, so you won't
// get flooded with warnings if this was the intent.
// Problems are: textures not visible, display lists VERY slow (Racer)
if(fWarned==FALSE&&
glXGetCurrentContext()!=QCV->GetGLContext()->GetGLXContext())
{
qwarn("Textures being created outside of QCV; probably NOT wanted");
fWarned=TRUE;
}
//qdbg("DTexture:CreateTexture(); texture ID %d in ctx %p\n",textureID,glXGetCurrentContext());
#endif
// Create texture in system (no image yet)
glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
glPixelStorei(GL_UNPACK_SKIP_ROWS,0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS,0);
//glPixelStorei(GL_UNPACK_ALIGNMENT,1);
/*glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,
bm->GetWidth(),bm->GetHeight(),0,GL_RGBA,GL_UNSIGNED_BYTE,bm->GetBuffer());
*/
#ifdef WIN32
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,wid,hgt,0,
GL_RGBA,GL_UNSIGNED_BYTE,0);
#else
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8_EXT,wid,hgt,0,
GL_RGBA,GL_UNSIGNED_BYTE,0);
#endif
// Default settings for texturing (taken from the D3 preferences)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,dglobal.prefs.minFilter);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,dglobal.prefs.maxFilter);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,dglobal.prefs.wrapS);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,dglobal.prefs.wrapT);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,dglobal.prefs.envMode);
#ifdef OBS
qdbg("texID %d; set envmode 0x%x\n",textureID,dglobal.prefs.envMode);
{
int n; glGetTexEnviv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,&n);
qdbg("DTexture:Create PRE; envmode=0x%x, MODULATE=%x, REPLACE=%x\n",
n,GL_MODULATE,GL_REPLACE);
}
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
{
int n; glGetTexEnviv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,&n);
qdbg("DTexture:Create IN-bind; envmode=0x%x, MODULATE=%x, REPLACE=%x\n",
n,GL_MODULATE,GL_REPLACE);
}
glBindTexture(GL_TEXTURE_2D,textureID);
{
int n; glGetTexEnviv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,&n);
qdbg("DTexture:Create POST-bind; envmode=0x%x, MODULATE=%x, REPLACE=%x\n",
n,GL_MODULATE,GL_REPLACE);
}
#endif
}
void DTexture::Select()
// Select our texture (selects parameters as well/OpenGL)
{
QASSERT_V(gl); // No OpenGL context; texture not created
//qdbg("DTexture:Select(): id %d into context %p\n",textureID,glXGetCurrentContext());
//qdbg("DTexture:Select(): id %d into context %p\n",textureID,gl);
gl->Select();
#ifdef USE_ISTEXTURE_TEST
// Check first to see if texture exists in this OpenGL context
if(!glIsTexture(textureID))
{ qwarn("DTexture::Select(); texture ID %d does not exist in current GLCtx");
return;
}
#endif
glBindTexture(GL_TEXTURE_2D,textureID);
}
int DTexture::GetWidth()
// Returns width of actual texture (may not match used part of texture)
{
return wid;
}
int DTexture::GetHeight()
// Returns height of actual texture (may not match used part of texture)
{
return hgt;
}
void DTexture::SetWrap(int sWrap,int tWrap,int rWrap,int qWrap)
// Sets wrapping functions for the texture; default is to repeat the texture
// Possible values are CLAMP and REPEAT. OpenGL has more (CLAMP_TO_BORDER).
// Note: this function implicity selects the texture
{
QASSERT(rWrap==REPEAT&&qWrap==REPEAT); // r/q wrap NYI
Select();
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,sWrap);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,tWrap);
}
void DTexture::SetEnvMode(int mode)
// Set environment mode.
// Possible values are: MODULATE, ADD, REPLACE
// See also 'man gltexenv'
{
Select();
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,mode);
}
void DTexture::SetName(cstring s)
{
name=s;
}
/*****************
* BITMAP TEXTURE *
*****************/
#undef DBG_CLASS
#define DBG_CLASS "DBitMapTexture"
DBitMapTexture::DBitMapTexture(QBitMap *ibm)
: DTexture()
// Use an existing bitmap as a texture
{
DBG_C("ctor");
DBG_ARG_P(ibm);
int w,h;
QBitMap *tbm=0;
bm=ibm;
bwid=bm->GetWidth();
bhgt=bm->GetHeight();
// Find 2**n texture size to play movie in
w=QNearestPowerOf2(bwid);
h=QNearestPowerOf2(bhgt);
SetSize(w,h);
if(bwid!=wid||bhgt!=hgt)
{ // Bitmap is not directly usable
// Either use SKIP_PIXELS etc
// or allocate a new bitmap where you put it in
tbm=new QBitMap(32,wid,hgt);
//qdbg("Copy into %dx%d the source bitmap %dx%d\n",wid,hgt,bwid,bhgt);
tbm->CopyPixelsFrom(bm,0,0,bwid,bhgt,0,0);
bm=tbm;
}
//qdbg("DBitMapTexture: creating texture %dx%d for bitmap %dx%d\n",w,h,bwid,bhgt);
CreateTexture();
// Install image as texture
//qdbg("installtex\n");
if(dglobal.prefs.UseMipMapping())
{
// Build all mipmaps
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,wid,hgt,GL_RGBA,GL_UNSIGNED_BYTE,
bm->GetBuffer());
} else
{
// No mipmaps; just 1 level of detail
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,wid,hgt,0,GL_RGBA,GL_UNSIGNED_BYTE,
bm->GetBuffer());
}
// Don't leave texture bitmap around
if(tbm)delete tbm;
//qdbg("DBitMapTex ret\n");
}
DBitMapTexture::~DBitMapTexture()
{
//qdbg("DBitMapTexture dtor\n");
}
/*******************
* DRAWABLE TEXTURE *
*******************/
DDrawableTexture::DDrawableTexture(QDrawable *_draw)
: DTexture()
// Create a texture for a drawable's contents
{
draw=_draw;
// Find 2**n texture size to store drawable in
int w,h;
w=QNearestPowerOf2(draw->GetWidth());
h=QNearestPowerOf2(draw->GetHeight());
SetSize(w,h);
//qdbg("DDrawbleTexture: creating texture %dx%d\n",w,h);
CreateTexture();
}
DDrawableTexture::~DDrawableTexture()
{
}
void DDrawableTexture::Refresh(bool front)
{
Select();
int dx,dy;
// Create texture in system (no image yet)
glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
glPixelStorei(GL_UNPACK_SKIP_ROWS,0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS,0);
dx=0; dy=0;
glPixelStorei(GL_PACK_ROW_LENGTH,1024); // Texture width
//glPixelStorei(GL_PACK_ROW_LENGTH,0); // Texture width
glPixelStorei(GL_PACK_SKIP_PIXELS,dx);
glPixelStorei(GL_PACK_SKIP_ROWS,dy);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glPixelStorei(GL_PACK_ALIGNMENT,1);
glDisable(GL_BLEND);
if(front)glReadBuffer(GL_FRONT);
else glReadBuffer(GL_BACK);
QShowGLErrors("pre glCopyTexSubImage2D");
glCopyTexSubImage2D(GL_TEXTURE_2D,0, 0,1024-576,
0,0, draw->GetWidth(),draw->GetHeight());
QShowGLErrors("post glCopyTexSubImage2D");
glReadBuffer(GL_BACK);
}
/****************
* MOVIE TEXTURE *
****************/
#ifndef WIN32
DMovieTexture::DMovieTexture(QMovie *mv)
: DTexture()
// Create movie texture; render movie 'mv' into a pbuffer
// Note that the texture is rounded to 2**n size, so 720x576 becomes 1024x768
// for the pbuffer size.
{
int w,h;
movie=mv;
// Normal dims of picture (need to cut out movie images from texture)
mwid=movie->GetImageTrack()->GetImageWidth();
mhgt=movie->GetImageTrack()->GetImageHeight();
// Find 2**n texture size to play movie in
w=QNearestPowerOf2(mwid);
h=QNearestPowerOf2(mhgt);
qdbg("DMovieTexture: creating texture %dx%d to play %dx%d in\n",w,h,mwid,mhgt);
pbuf=new QDMPBuffer(w,h);
SetSize(w,h);
// Create pbuffer (where the movies frames will be rendered)
//pbuf=new QDMPBuffer(wid,hgt);
// Create a DMbuffer to be used as the color buffer of 'pbuf'
pool=new QDMBPool(1,wid*hgt*4,FALSE,FALSE);
//pool=new QDMBPool(1,((wid*hgt*4)+0xFFFF)&~0xFFFF,FALSE,FALSE);
//pool=new QDMBPool(1,((wid*hgt*4)+0xFFFF)&~0xFFFF,TRUE,TRUE);
pool->AddProducer(pbuf);
if(!pool->Create())
{ qerr("DMovieTexture ctor: can't create pool for texture dmbuffer");
// And crash...?
}
//SetCurrentQGLContext(0);
//app->GetBC()->GetCanvas()->Select();
CreateTexture();
dmbuf=pool->AllocateDMBuffer();
// Complete pbuffer by linking 'dmbuf' as its color buffer
pbuf->Associate(dmbuf);
// Install pbuffer as texture
pbuf->CopyTexture(app->GetBC()->GetCanvas()->GetGLContext());
QShowGLErrors("DMovieTexture ctor; pbuf CopyTexture");
#ifndef WIN32
// Fit renders into texture
MVrect r;
r.left=0; r.right=mwid;
//r.top=0; r.bottom=thgt;
r.top=100; r.bottom=100+mhgt;
r.top=100+mhgt; r.bottom=100;
r.top=hgt-1; r.bottom=hgt-mhgt-1;
//if(!mvSetMovieRect(movie->GetImageTrack()->GetMVid(),r))
if(!mvSetMovieRect(movie->GetMVid(),r))
QShowMVErrors("DMovieTexture: mvSetMovieRect");
#endif
// Setup OpenGL rendering view
pbuf->Select();
glViewport(0,0,wid,hgt);
QShowGLErrors("viewport");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0,wid,0,hgt,-1,1);
glDisable(GL_TEXTURE_2D);
// Reset GLX context
//SetCurrentQGLContext(0);
//app->GetBC()->GetCanvas()->Select();
}
DMovieTexture::~DMovieTexture()
// Destroys pbuffer, DMbuffer, bufferpool
{
//qdbg("DMovieTexture dtor\n");
delete pbuf;
delete dmbuf;
delete pool;
}
static int done;
bool DMovieTexture::Render()
// Selects our pbuffer context and render the current frame into the pbuffer
// NOTES:
// - Turns off blending
{
if(done)return TRUE;
//done=1;
//qdbg("DMT:Render()\n");
// Select us as current texture
Select();
pbuf->Select();
//#ifdef ND_DONE
glViewport(0,0,wid,hgt);
QShowGLErrors("viewport");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0,wid,0,hgt,-1,1);
glDisable(GL_TEXTURE_2D);
/*
float c=rand()&255;
c/=256;
glClearColor(.4,.5,c,1);
glClear(GL_COLOR_BUFFER_BIT);
QShowGLErrors("matrix");
*/
//#endif
movie->RenderToOpenGL();
glDisable(GL_BLEND);
glRasterPos2i(0,0);
//pbuf->CopyTexture(app->GetBC()->GetCanvas()->GetGLContext());
QShowGLErrors("DMT:Render; CopyTexture");
// Clear GLXContext cache
//SetCurrentQGLContext(0);
//app->GetBC()->GetCanvas()->Select();
//app->GetBC()->Swap(); QNap(50);
//app->GetBC()->Swap(); QNap(50);
return TRUE;
}
bool DMovieTexture::SetCurFrame(int frame)
// Sets current frame
// BUGS:
// - Currently does nothing; should set movie frame
{
return TRUE;
}
bool DMovieTexture::Advance()
// Shortcut to advance movie 1 frame. Returns TRUE if movie is still
// playing, FALSE if movie has ended
{
movie->Advance();
if(movie->IsPlaying())return true;
return false;
}
#endif
// ifndef Win32