2
* Copyright © 2005 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
36
#include <core/core.h>
37
#include <opengl/texture.h>
38
#include <privatetexture.h>
41
std::map<Damage, TfpTexture*> boundPixmapTex;
43
static GLTexture::Matrix _identity_matrix = {
49
GLTexture::List::List () :
50
std::vector<GLTexture *> (0)
54
GLTexture::List::List (unsigned int size) :
55
std::vector<GLTexture *> (size)
57
for (unsigned int i = 0; i < size; i++)
61
GLTexture::List::List (const GLTexture::List &c)
64
for (unsigned int i = 0; i < c.size (); i++)
67
GLTexture::incRef (c[i]);
71
GLTexture::List::~List ()
73
foreach (GLTexture *t, *this)
74
GLTexture::decRef (t);
78
GLTexture::List::operator= (const GLTexture::List &c)
82
for (unsigned int i = 0; i < c.size (); i++)
85
GLTexture::incRef (c[i]);
91
GLTexture::List::clear ()
93
foreach (GLTexture *t, *this)
94
GLTexture::decRef (t);
95
std::vector <GLTexture *>::clear ();
98
GLTexture::GLTexture () :
99
CompRect (0, 0, 0, 0),
100
priv (new PrivateTexture (this))
104
GLTexture::~GLTexture ()
110
PrivateTexture::PrivateTexture (GLTexture *texture) :
113
target (GL_TEXTURE_2D),
115
wrap (GL_CLAMP_TO_EDGE),
116
matrix (_identity_matrix),
118
mipmapSupport (false),
122
glGenTextures (1, &name);
125
PrivateTexture::~PrivateTexture ()
129
glDeleteTextures (1, &name);
134
GLTexture::name () const
140
GLTexture::target () const
145
const GLTexture::Matrix &
146
GLTexture::matrix () const
152
GLTexture::mipmap () const
154
return priv->mipmap & priv->mipmapSupport;
158
GLTexture::filter () const
164
GLTexture::enable (GLTexture::Filter filter)
166
GLScreen *gs = GLScreen::get (screen);
167
glEnable (priv->target);
168
glBindTexture (priv->target, priv->name);
172
if (priv->filter != GL_NEAREST)
174
glTexParameteri (priv->target,
175
GL_TEXTURE_MIN_FILTER,
177
glTexParameteri (priv->target,
178
GL_TEXTURE_MAG_FILTER,
181
priv->filter = GL_NEAREST;
184
else if (priv->filter != gs->textureFilter ())
186
if (gs->textureFilter () == GL_LINEAR_MIPMAP_LINEAR)
188
if (GL::textureNonPowerOfTwo && GL::fbo && priv->mipmap)
190
glTexParameteri (priv->target,
191
GL_TEXTURE_MIN_FILTER,
192
GL_LINEAR_MIPMAP_LINEAR);
194
if (priv->filter != GL_LINEAR)
195
glTexParameteri (priv->target,
196
GL_TEXTURE_MAG_FILTER,
199
priv->filter = GL_LINEAR_MIPMAP_LINEAR;
201
else if (priv->filter != GL_LINEAR)
203
glTexParameteri (priv->target,
204
GL_TEXTURE_MIN_FILTER,
206
glTexParameteri (priv->target,
207
GL_TEXTURE_MAG_FILTER,
210
priv->filter = GL_LINEAR;
215
glTexParameteri (priv->target,
216
GL_TEXTURE_MIN_FILTER,
217
gs->textureFilter ());
218
glTexParameteri (priv->target,
219
GL_TEXTURE_MAG_FILTER,
220
gs->textureFilter ());
222
priv->filter = gs->textureFilter ();
226
if (priv->filter == GL_LINEAR_MIPMAP_LINEAR)
230
(*GL::generateMipmap) (priv->target);
231
priv->initial = false;
237
GLTexture::disable ()
239
glBindTexture (priv->target, 0);
240
glDisable (priv->target);
244
GLTexture::setData (GLenum target, Matrix &m, bool mipmap)
246
priv->target = target;
248
priv->mipmapSupport = mipmap;
252
GLTexture::setMipmap (bool enable)
254
priv->mipmap = enable;
258
GLTexture::setFilter (GLenum filter)
260
glBindTexture (priv->target, priv->name);
262
priv->filter = filter;
264
glTexParameteri (priv->target, GL_TEXTURE_MIN_FILTER, filter);
265
glTexParameteri (priv->target, GL_TEXTURE_MAG_FILTER, filter);
267
glBindTexture (priv->target, 0);
271
GLTexture::setWrap (GLenum wrap)
273
glBindTexture (priv->target, priv->name);
275
priv->wrap = GL_CLAMP_TO_EDGE;
277
glTexParameteri (priv->target, GL_TEXTURE_WRAP_S, wrap);
278
glTexParameteri (priv->target, GL_TEXTURE_WRAP_T, wrap);
280
glBindTexture (priv->target, 0);
284
PrivateTexture::loadImageData (const char *image,
290
#warning Add support for multiple textures
291
if ((int) width > GL::maxTextureSize || (int) height > GL::maxTextureSize)
292
return GLTexture::List ();
294
GLTexture::List rv (1);
295
GLTexture *t = new GLTexture ();
298
GLTexture::Matrix matrix = _identity_matrix;
299
GLint internalFormat;
304
if (GL::textureNonPowerOfTwo ||
305
(POWER_OF_TWO (width) && POWER_OF_TWO (height)))
307
target = GL_TEXTURE_2D;
308
matrix.xx = 1.0f / width;
309
matrix.yy = 1.0f / height;
315
target = GL_TEXTURE_RECTANGLE_NV;
322
t->setData (target, matrix, mipmap);
323
t->setGeometry (0, 0, width, height);
325
glBindTexture (target, t->name ());
328
(GLScreen::get(screen)->getOption ("texture_compression")->value ().b ()
329
&& GL::textureCompression ? GL_COMPRESSED_RGBA_ARB : GL_RGBA);
331
glTexImage2D (target, 0, internalFormat, width, height, 0,
332
format, type, image);
334
t->setFilter (GL_NEAREST);
335
t->setWrap (GL_CLAMP_TO_EDGE);
341
GLTexture::imageBufferToTexture (const char *image,
344
#if IMAGE_BYTE_ORDER == MSBFirst
345
return PrivateTexture::loadImageData (image, size.width (), size.height (),
346
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
348
return PrivateTexture::loadImageData (image, size.width (), size.height (),
349
GL_BGRA, GL_UNSIGNED_BYTE);
354
GLTexture::imageDataToTexture (const char *image,
359
return PrivateTexture::loadImageData (image, size.width (), size.height (),
365
GLTexture::readImageToTexture (CompString &imageFileName,
370
if (!screen->readImageFromFile (imageFileName, size, image) || !image)
371
return GLTexture::List ();
374
GLTexture::imageBufferToTexture ((char *)image, size);
382
GLTexture::decRef (GLTexture *tex)
384
tex->priv->refCount--;
385
if (tex->priv->refCount <= 0)
390
GLTexture::incRef (GLTexture *tex)
392
tex->priv->refCount++;
396
GLTexture::bindPixmapToTexture (Pixmap pixmap,
403
foreach (BindPixmapProc &proc, GLScreen::get (screen)->priv->bindPixmap)
406
rv = proc (pixmap, width, height, depth);
410
return GLTexture::List ();
413
TfpTexture::TfpTexture () :
420
TfpTexture::~TfpTexture ()
424
glEnable (target ());
426
glBindTexture (target (), name ());
428
(*GL::releaseTexImage) (screen->dpy (), pixmap, GLX_FRONT_LEFT_EXT);
430
glBindTexture (target (), 0);
431
glDisable (target ());
433
glXDestroyGLXPixmap (screen->dpy (), pixmap);
435
boundPixmapTex.erase (damage);
436
XDamageDestroy (screen->dpy (), damage);
441
TfpTexture::bindPixmapToTexture (Pixmap pixmap,
446
if ((int) width > GL::maxTextureSize || (int) height > GL::maxTextureSize ||
447
!GL::textureFromPixmap)
448
return GLTexture::List ();
450
GLTexture::List rv (1);
451
TfpTexture *tex = NULL;
452
unsigned int target = 0;
453
GLenum texTarget = GL_TEXTURE_2D;
454
GLXPixmap glxPixmap = None;
455
GLTexture::Matrix matrix = _identity_matrix;
458
GLScreen::get (screen)->glxPixmapFBConfig (depth);
459
int attribs[7], i = 0;
461
if (!config->fbConfig)
463
compLogMessage ("core", CompLogLevelWarn,
464
"No GLXFBConfig for depth %d",
467
return GLTexture::List ();
470
attribs[i++] = GLX_TEXTURE_FORMAT_EXT;
471
attribs[i++] = config->textureFormat;
472
attribs[i++] = GLX_MIPMAP_TEXTURE_EXT;
473
attribs[i++] = config->mipmap;
475
/* If no texture target is specified in the fbconfig, or only the
476
TEXTURE_2D target is specified and GL_texture_non_power_of_two
477
is not supported, then allow the server to choose the texture target. */
478
if (config->textureTargets & GLX_TEXTURE_2D_BIT_EXT &&
479
(GL::textureNonPowerOfTwo ||
480
(POWER_OF_TWO (width) && POWER_OF_TWO (height))))
481
target = GLX_TEXTURE_2D_EXT;
482
else if (config->textureTargets & GLX_TEXTURE_RECTANGLE_BIT_EXT)
483
target = GLX_TEXTURE_RECTANGLE_EXT;
485
/* Workaround for broken texture from pixmap implementations,
486
that don't advertise any texture target in the fbconfig. */
489
if (!(config->textureTargets & GLX_TEXTURE_2D_BIT_EXT))
490
target = GLX_TEXTURE_RECTANGLE_EXT;
491
else if (!(config->textureTargets & GLX_TEXTURE_RECTANGLE_BIT_EXT))
492
target = GLX_TEXTURE_2D_EXT;
497
attribs[i++] = GLX_TEXTURE_TARGET_EXT;
498
attribs[i++] = target;
503
glxPixmap = (*GL::createPixmap) (screen->dpy (), config->fbConfig,
508
compLogMessage ("core", CompLogLevelWarn,
509
"glXCreatePixmap failed");
511
return GLTexture::List ();
515
(*GL::queryDrawable) (screen->dpy (), glxPixmap,
516
GLX_TEXTURE_TARGET_EXT, &target);
519
case GLX_TEXTURE_2D_EXT:
520
texTarget = GL_TEXTURE_2D;
522
matrix.xx = 1.0f / width;
523
if (config->yInverted)
525
matrix.yy = 1.0f / height;
530
matrix.yy = -1.0f / height;
533
mipmap = config->mipmap;
535
case GLX_TEXTURE_RECTANGLE_EXT:
536
texTarget = GL_TEXTURE_RECTANGLE_ARB;
539
if (config->yInverted)
552
compLogMessage ("core", CompLogLevelWarn,
553
"pixmap 0x%x can't be bound to texture",
556
glXDestroyGLXPixmap (screen->dpy (), glxPixmap);
559
return GLTexture::List ();
562
tex = new TfpTexture ();
563
tex->setData (texTarget, matrix, mipmap);
564
tex->setGeometry (0, 0, width, height);
565
tex->pixmap = glxPixmap;
569
glBindTexture (texTarget, tex->name ());
572
(*GL::bindTexImage) (screen->dpy (), glxPixmap, GLX_FRONT_LEFT_EXT, NULL);
574
tex->setFilter (GL_NEAREST);
575
tex->setWrap (GL_CLAMP_TO_EDGE);
577
glBindTexture (texTarget, 0);
579
tex->damage = XDamageCreate (screen->dpy (), pixmap,
580
XDamageReportRawRectangles);
581
boundPixmapTex[tex->damage] = tex;
587
TfpTexture::enable (GLTexture::Filter filter)
589
glEnable (target ());
590
glBindTexture (target (), name ());
592
if (damaged && pixmap)
594
(*GL::releaseTexImage) (screen->dpy (), pixmap, GLX_FRONT_LEFT_EXT);
595
(*GL::bindTexImage) (screen->dpy (), pixmap, GLX_FRONT_LEFT_EXT, NULL);
598
GLTexture::enable (filter);
600
if (this->filter () == GL_LINEAR_MIPMAP_LINEAR)
604
(*GL::generateMipmap) (target ());