Shared dri driver resources
This commit is contained in:
parent
b32a036059
commit
93a458840c
|
@ -0,0 +1,176 @@
|
||||||
|
/* $XFree86: xc/lib/GL/mesa/src/drv/common/depthtmp.h,v 1.5 2001/03/21 16:14:20 dawes Exp $ */
|
||||||
|
|
||||||
|
#ifndef DBG
|
||||||
|
#define DBG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_HW_DEPTH_SPANS
|
||||||
|
#define HAVE_HW_DEPTH_SPANS 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_HW_DEPTH_PIXELS
|
||||||
|
#define HAVE_HW_DEPTH_PIXELS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_READ_LOCK
|
||||||
|
#define HW_READ_LOCK() HW_LOCK()
|
||||||
|
#endif
|
||||||
|
#ifndef HW_READ_UNLOCK
|
||||||
|
#define HW_READ_UNLOCK() HW_UNLOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void TAG(WriteDepthSpan)( GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
const GLdepth *depth,
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1;
|
||||||
|
GLint n1;
|
||||||
|
LOCAL_DEPTH_VARS;
|
||||||
|
|
||||||
|
y = Y_FLIP( y );
|
||||||
|
|
||||||
|
#if HAVE_HW_DEPTH_SPANS
|
||||||
|
(void) x1; (void) n1;
|
||||||
|
|
||||||
|
if ( DBG ) fprintf( stderr, "WriteDepthSpan 0..%d (x1 %d)\n",
|
||||||
|
(int)n, (int)x );
|
||||||
|
|
||||||
|
WRITE_DEPTH_SPAN();
|
||||||
|
#else
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN( x, y, n, x1, n1, i );
|
||||||
|
|
||||||
|
if ( DBG ) fprintf( stderr, "WriteDepthSpan %d..%d (x1 %d)\n",
|
||||||
|
(int)i, (int)n1, (int)x1 );
|
||||||
|
|
||||||
|
if ( mask ) {
|
||||||
|
for ( ; i < n1 ; i++, x1++ ) {
|
||||||
|
if ( mask[i] ) WRITE_DEPTH( x1, y, depth[i] );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for ( ; i < n1 ; i++, x1++ ) {
|
||||||
|
WRITE_DEPTH( x1, y, depth[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TAG(WriteDepthPixels)( GLcontext *ctx,
|
||||||
|
GLuint n,
|
||||||
|
const GLint x[],
|
||||||
|
const GLint y[],
|
||||||
|
const GLdepth depth[],
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
LOCAL_DEPTH_VARS;
|
||||||
|
|
||||||
|
if ( DBG ) fprintf( stderr, "WriteDepthPixels\n" );
|
||||||
|
|
||||||
|
#if HAVE_HW_DEPTH_PIXELS
|
||||||
|
(void) i;
|
||||||
|
|
||||||
|
WRITE_DEPTH_PIXELS();
|
||||||
|
#else
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
for ( i = 0 ; i < n ; i++ ) {
|
||||||
|
if ( mask[i] ) {
|
||||||
|
const int fy = Y_FLIP( y[i] );
|
||||||
|
if ( CLIPPIXEL( x[i], fy ) )
|
||||||
|
WRITE_DEPTH( x[i], fy, depth[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read depth spans and pixels
|
||||||
|
*/
|
||||||
|
static void TAG(ReadDepthSpan)( GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
GLdepth depth[] )
|
||||||
|
{
|
||||||
|
HW_READ_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1, n1;
|
||||||
|
LOCAL_DEPTH_VARS;
|
||||||
|
|
||||||
|
y = Y_FLIP( y );
|
||||||
|
|
||||||
|
if ( DBG ) fprintf( stderr, "ReadDepthSpan\n" );
|
||||||
|
|
||||||
|
#if HAVE_HW_DEPTH_SPANS
|
||||||
|
(void) x1; (void) n1;
|
||||||
|
|
||||||
|
READ_DEPTH_SPAN();
|
||||||
|
#else
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN( x, y, n, x1, n1, i );
|
||||||
|
for ( ; i < n1 ; i++ )
|
||||||
|
READ_DEPTH( depth[i], (x1+i), y );
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
HW_READ_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TAG(ReadDepthPixels)( GLcontext *ctx, GLuint n,
|
||||||
|
const GLint x[], const GLint y[],
|
||||||
|
GLdepth depth[] )
|
||||||
|
{
|
||||||
|
HW_READ_LOCK()
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
LOCAL_DEPTH_VARS;
|
||||||
|
|
||||||
|
if ( DBG ) fprintf( stderr, "ReadDepthPixels\n" );
|
||||||
|
|
||||||
|
#if HAVE_HW_DEPTH_PIXELS
|
||||||
|
(void) i;
|
||||||
|
|
||||||
|
READ_DEPTH_PIXELS();
|
||||||
|
#else
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
for ( i = 0 ; i < n ;i++ ) {
|
||||||
|
int fy = Y_FLIP( y[i] );
|
||||||
|
if ( CLIPPIXEL( x[i], fy ) )
|
||||||
|
READ_DEPTH( depth[i], x[i], fy );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
HW_READ_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_HW_DEPTH_SPANS
|
||||||
|
#undef WRITE_DEPTH_SPAN
|
||||||
|
#undef WRITE_DEPTH_PIXELS
|
||||||
|
#undef READ_DEPTH_SPAN
|
||||||
|
#undef READ_DEPTH_PIXELS
|
||||||
|
#else
|
||||||
|
#undef WRITE_DEPTH
|
||||||
|
#undef READ_DEPTH
|
||||||
|
#endif
|
||||||
|
#undef TAG
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* GLX Hardware Device Driver common code
|
||||||
|
*
|
||||||
|
* Based on the original MGA G200 driver (c) 1999 Wittawat Yamwong
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Wittawat Yamwong <Wittawat.Yamwong@stud.uni-hannover.de>
|
||||||
|
*/
|
||||||
|
/* $XFree86: xc/lib/GL/mesa/src/drv/common/hwlog.c,v 1.3 2001/08/18 02:51:03 dawes Exp $ */
|
||||||
|
|
||||||
|
#include "hwlog.h"
|
||||||
|
hwlog_t hwlog = { 0,0,0, "[???] "};
|
||||||
|
|
||||||
|
|
||||||
|
/* Should be shared, but is this a good place for it?
|
||||||
|
*/
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
int usec( void )
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
struct timezone tz;
|
||||||
|
|
||||||
|
gettimeofday( &tv, &tz );
|
||||||
|
|
||||||
|
return (tv.tv_sec & 2047) * 1000000 + tv.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HW_LOG_ENABLED
|
||||||
|
int hwOpenLog(const char *filename, char *prefix)
|
||||||
|
{
|
||||||
|
hwCloseLog();
|
||||||
|
hwSetLogLevel(0);
|
||||||
|
hwlog.prefix=prefix;
|
||||||
|
if (!filename)
|
||||||
|
return -1;
|
||||||
|
if ((hwlog.file = fopen(filename,"w")) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hwCloseLog()
|
||||||
|
{
|
||||||
|
if (hwlog.file) {
|
||||||
|
fclose(hwlog.file);
|
||||||
|
hwlog.file = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwIsLogReady()
|
||||||
|
{
|
||||||
|
return (hwlog.file != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hwSetLogLevel(int level)
|
||||||
|
{
|
||||||
|
hwlog.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwGetLogLevel()
|
||||||
|
{
|
||||||
|
return hwlog.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hwLog(int level, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,format);
|
||||||
|
hwLogv(level,format,ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hwLogv(int l, const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
if (hwlog.file && (l <= hwlog.level)) {
|
||||||
|
vfprintf(hwlog.file,format,ap);
|
||||||
|
fflush(hwlog.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hwMsg(int l, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
|
||||||
|
if (l <= hwlog.level) {
|
||||||
|
if (hwIsLogReady()) {
|
||||||
|
int t = usec();
|
||||||
|
|
||||||
|
hwLog(l, "%6i:", t - hwlog.timeTemp);
|
||||||
|
hwlog.timeTemp = t;
|
||||||
|
hwLogv(l, format, ap);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, hwlog.prefix);
|
||||||
|
vfprintf(stderr, format, ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ifdef HW_LOG_ENABLED */
|
||||||
|
|
||||||
|
int hwlogdummy()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void hwError(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
|
||||||
|
fprintf(stderr, hwlog.prefix);
|
||||||
|
vfprintf(stderr, format, ap);
|
||||||
|
hwLogv(0, format, ap);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* GLX Hardware Device Driver common code
|
||||||
|
*
|
||||||
|
* Based on the original MGA G200 driver (c) 1999 Wittawat Yamwong
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Wittawat Yamwong <Wittawat.Yamwong@stud.uni-hannover.de>
|
||||||
|
*/
|
||||||
|
/* $XFree86: xc/lib/GL/mesa/src/drv/common/hwlog.h,v 1.5 2001/10/31 23:22:57 tsi Exp $ */
|
||||||
|
|
||||||
|
/* Usage:
|
||||||
|
* - use mgaError for error messages. Always write to X error and log file.
|
||||||
|
* - use mgaMsg for debugging. Can be disabled by undefining MGA_LOG_ENABLED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HWLOG_INC
|
||||||
|
#define HWLOG_INC
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define DBG_LEVEL_BASE 1
|
||||||
|
#define DBG_LEVEL_VERBOSE 10
|
||||||
|
#define DBG_LEVEL_ENTEREXIT 20
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
int level;
|
||||||
|
unsigned int timeTemp;
|
||||||
|
char *prefix;
|
||||||
|
} hwlog_t;
|
||||||
|
|
||||||
|
extern hwlog_t hwlog;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HW_LOG_ENABLED
|
||||||
|
|
||||||
|
/* open and close log file. */
|
||||||
|
int hwOpenLog(const char *filename, char *prefix);
|
||||||
|
void hwCloseLog(void);
|
||||||
|
|
||||||
|
/* return 1 if log file is succesfully opened */
|
||||||
|
int hwIsLogReady(void);
|
||||||
|
|
||||||
|
/* set current log level to 'level'. Messages with level less than or equal
|
||||||
|
the current log level will be written to the log file. */
|
||||||
|
void hwSetLogLevel(int level);
|
||||||
|
int hwGetLogLevel(void);
|
||||||
|
|
||||||
|
/* hwLog and hwLogv write a message to the log file. */
|
||||||
|
/* do not call these directly, use hwMsg() instead */
|
||||||
|
void hwLog(int level, const char *format, ...);
|
||||||
|
void hwLogv(int level, const char *format, va_list ap);
|
||||||
|
|
||||||
|
int usec( void );
|
||||||
|
|
||||||
|
/* hwMsg writes a message to the log file or to the standard X error file. */
|
||||||
|
void hwMsg(int level, const char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
static __inline__ int hwOpenLog(const char *f, char *prefix) { hwlog.prefix=prefix; return -1; }
|
||||||
|
#define hwIsLogReady() (0)
|
||||||
|
#define hwGetLogLevel() (-1)
|
||||||
|
#define hwLogLevel(n) (0)
|
||||||
|
#define hwLog()
|
||||||
|
#define hwMsg()
|
||||||
|
|
||||||
|
#define hwCloseLog()
|
||||||
|
#define hwSetLogLevel(x)
|
||||||
|
#define hwLogv(l,f,a)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void hwError(const char *format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* GLX Hardware Device Driver common code
|
||||||
|
* Copyright (C) 1999 Wittawat Yamwong
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* $XFree86: xc/lib/GL/mesa/src/drv/common/mm.c,v 1.4 2002/10/30 12:51:27 alanh Exp $ */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "mm.h"
|
||||||
|
#include "hwlog.h"
|
||||||
|
|
||||||
|
|
||||||
|
void mmDumpMemInfo( memHeap_t *heap )
|
||||||
|
{
|
||||||
|
TMemBlock *p;
|
||||||
|
|
||||||
|
fprintf(stderr, "Memory heap %p:\n", heap);
|
||||||
|
if (heap == 0) {
|
||||||
|
fprintf(stderr, " heap == 0\n");
|
||||||
|
} else {
|
||||||
|
p = (TMemBlock *)heap;
|
||||||
|
while (p) {
|
||||||
|
fprintf(stderr, " Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
|
||||||
|
p->free ? '.':'U',
|
||||||
|
p->reserved ? 'R':'.');
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "End of memory blocks\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
memHeap_t *mmInit(int ofs,
|
||||||
|
int size)
|
||||||
|
{
|
||||||
|
PMemBlock blocks;
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
blocks = (TMemBlock *) calloc(1,sizeof(TMemBlock));
|
||||||
|
if (blocks) {
|
||||||
|
blocks->ofs = ofs;
|
||||||
|
blocks->size = size;
|
||||||
|
blocks->free = 1;
|
||||||
|
return (memHeap_t *)blocks;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static TMemBlock* SliceBlock(TMemBlock *p,
|
||||||
|
int startofs, int size,
|
||||||
|
int reserved, int alignment)
|
||||||
|
{
|
||||||
|
TMemBlock *newblock;
|
||||||
|
|
||||||
|
/* break left */
|
||||||
|
if (startofs > p->ofs) {
|
||||||
|
newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
|
||||||
|
if (!newblock)
|
||||||
|
return NULL;
|
||||||
|
newblock->ofs = startofs;
|
||||||
|
newblock->size = p->size - (startofs - p->ofs);
|
||||||
|
newblock->free = 1;
|
||||||
|
newblock->next = p->next;
|
||||||
|
p->size -= newblock->size;
|
||||||
|
p->next = newblock;
|
||||||
|
p = newblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* break right */
|
||||||
|
if (size < p->size) {
|
||||||
|
newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
|
||||||
|
if (!newblock)
|
||||||
|
return NULL;
|
||||||
|
newblock->ofs = startofs + size;
|
||||||
|
newblock->size = p->size - size;
|
||||||
|
newblock->free = 1;
|
||||||
|
newblock->next = p->next;
|
||||||
|
p->size = size;
|
||||||
|
p->next = newblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* p = middle block */
|
||||||
|
p->align = alignment;
|
||||||
|
p->free = 0;
|
||||||
|
p->reserved = reserved;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
|
||||||
|
{
|
||||||
|
int mask,startofs,endofs;
|
||||||
|
TMemBlock *p;
|
||||||
|
|
||||||
|
if (!heap || align2 < 0 || size <= 0)
|
||||||
|
return NULL;
|
||||||
|
mask = (1 << align2)-1;
|
||||||
|
startofs = 0;
|
||||||
|
p = (TMemBlock *)heap;
|
||||||
|
while (p) {
|
||||||
|
if ((p)->free) {
|
||||||
|
startofs = (p->ofs + mask) & ~mask;
|
||||||
|
if ( startofs < startSearch ) {
|
||||||
|
startofs = startSearch;
|
||||||
|
}
|
||||||
|
endofs = startofs+size;
|
||||||
|
if (endofs <= (p->ofs+p->size))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
if (!p)
|
||||||
|
return NULL;
|
||||||
|
p = SliceBlock(p,startofs,size,0,mask+1);
|
||||||
|
p->heap = heap;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ int Join2Blocks(TMemBlock *p)
|
||||||
|
{
|
||||||
|
if (p->free && p->next && p->next->free) {
|
||||||
|
TMemBlock *q = p->next;
|
||||||
|
p->size += q->size;
|
||||||
|
p->next = q->next;
|
||||||
|
free(q);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mmFreeMem(PMemBlock b)
|
||||||
|
{
|
||||||
|
TMemBlock *p,*prev;
|
||||||
|
|
||||||
|
if (!b)
|
||||||
|
return 0;
|
||||||
|
if (!b->heap) {
|
||||||
|
fprintf(stderr, "no heap\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p = b->heap;
|
||||||
|
prev = NULL;
|
||||||
|
while (p && p != b) {
|
||||||
|
prev = p;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
if (!p || p->free || p->reserved) {
|
||||||
|
if (!p)
|
||||||
|
fprintf(stderr, "block not found in heap\n");
|
||||||
|
else if (p->free)
|
||||||
|
fprintf(stderr, "block already free\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "block is reserved\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p->free = 1;
|
||||||
|
Join2Blocks(p);
|
||||||
|
if (prev)
|
||||||
|
Join2Blocks(prev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mmDestroy(memHeap_t *heap)
|
||||||
|
{
|
||||||
|
TMemBlock *p,*q;
|
||||||
|
|
||||||
|
if (!heap)
|
||||||
|
return;
|
||||||
|
p = (TMemBlock *)heap;
|
||||||
|
while (p) {
|
||||||
|
q = p->next;
|
||||||
|
free(p);
|
||||||
|
p = q;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* GLX Hardware Device Driver common code
|
||||||
|
* Copyright (C) 1999 Keith Whitwell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MM_INC
|
||||||
|
#define MM_INC
|
||||||
|
|
||||||
|
struct mem_block_t {
|
||||||
|
struct mem_block_t *next;
|
||||||
|
struct mem_block_t *heap;
|
||||||
|
int ofs,size;
|
||||||
|
int align;
|
||||||
|
int free:1;
|
||||||
|
int reserved:1;
|
||||||
|
};
|
||||||
|
typedef struct mem_block_t TMemBlock;
|
||||||
|
typedef struct mem_block_t *PMemBlock;
|
||||||
|
|
||||||
|
/* a heap is just the first block in a chain */
|
||||||
|
typedef struct mem_block_t memHeap_t;
|
||||||
|
|
||||||
|
static __inline__ int mmBlockSize(PMemBlock b)
|
||||||
|
{ return b->size; }
|
||||||
|
|
||||||
|
static __inline__ int mmOffset(PMemBlock b)
|
||||||
|
{ return b->ofs; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* input: total size in bytes
|
||||||
|
* return: a heap pointer if OK, NULL if error
|
||||||
|
*/
|
||||||
|
memHeap_t *mmInit( int ofs, int size );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate 'size' bytes with 2^align2 bytes alignment,
|
||||||
|
* restrict the search to free memory after 'startSearch'
|
||||||
|
* depth and back buffers should be in different 4mb banks
|
||||||
|
* to get better page hits if possible
|
||||||
|
* input: size = size of block
|
||||||
|
* align2 = 2^align2 bytes alignment
|
||||||
|
* startSearch = linear offset from start of heap to begin search
|
||||||
|
* return: pointer to the allocated block, 0 if error
|
||||||
|
*/
|
||||||
|
PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2,
|
||||||
|
int startSearch );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free block starts at offset
|
||||||
|
* input: pointer to a block
|
||||||
|
* return: 0 if OK, -1 if error
|
||||||
|
*/
|
||||||
|
int mmFreeMem( PMemBlock b );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* destroy MM
|
||||||
|
*/
|
||||||
|
void mmDestroy( memHeap_t *mmInit );
|
||||||
|
|
||||||
|
/* For debuging purpose. */
|
||||||
|
void mmDumpMemInfo( memHeap_t *mmInit );
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,560 @@
|
||||||
|
/* mmx.h
|
||||||
|
|
||||||
|
MultiMedia eXtensions GCC interface library for IA32.
|
||||||
|
|
||||||
|
To use this library, simply include this header file
|
||||||
|
and compile with GCC. You MUST have inlining enabled
|
||||||
|
in order for mmx_ok() to work; this can be done by
|
||||||
|
simply using -O on the GCC command line.
|
||||||
|
|
||||||
|
Compiling with -DMMX_TRACE will cause detailed trace
|
||||||
|
output to be sent to stderr for each mmx operation.
|
||||||
|
This adds lots of code, and obviously slows execution to
|
||||||
|
a crawl, but can be very useful for debugging.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
|
||||||
|
LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
1997-98 by H. Dietz and R. Fisher
|
||||||
|
|
||||||
|
History:
|
||||||
|
97-98* R.Fisher Early versions
|
||||||
|
980501 R.Fisher Original Release
|
||||||
|
980611* H.Dietz Rewrite, correctly implementing inlines, and
|
||||||
|
R.Fisher including direct register accesses.
|
||||||
|
980616 R.Fisher Release of 980611 as 980616.
|
||||||
|
980714 R.Fisher Minor corrections to Makefile, etc.
|
||||||
|
980715 R.Fisher mmx_ok() now prevents optimizer from using
|
||||||
|
clobbered values.
|
||||||
|
mmx_ok() now checks if cpuid instruction is
|
||||||
|
available before trying to use it.
|
||||||
|
980726* R.Fisher mm_support() searches for AMD 3DNow, Cyrix
|
||||||
|
Extended MMX, and standard MMX. It returns a
|
||||||
|
value which is positive if any of these are
|
||||||
|
supported, and can be masked with constants to
|
||||||
|
see which. mmx_ok() is now a call to this
|
||||||
|
980726* R.Fisher Added i2r support for shift functions
|
||||||
|
980919 R.Fisher Fixed AMD extended feature recognition bug.
|
||||||
|
980921 R.Fisher Added definition/check for _MMX_H.
|
||||||
|
Added "float s[2]" to mmx_t for use with
|
||||||
|
3DNow and EMMX. So same mmx_t can be used.
|
||||||
|
981013 R.Fisher Fixed cpuid function 1 bug (looked at wrong reg)
|
||||||
|
Fixed psllq_i2r error in mmxtest.c
|
||||||
|
|
||||||
|
* Unreleased (internal or interim) versions
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
It appears that the latest gas has the pand problem fixed, therefore
|
||||||
|
I'll undefine BROKEN_PAND by default.
|
||||||
|
String compares may be quicker than the multiple test/jumps in vendor
|
||||||
|
test sequence in mmx_ok(), but I'm not concerned with that right now.
|
||||||
|
|
||||||
|
Acknowledgments:
|
||||||
|
Jussi Laako for pointing out the errors ultimately found to be
|
||||||
|
connected to the failure to notify the optimizer of clobbered values.
|
||||||
|
Roger Hardiman for reminding us that CPUID isn't everywhere, and that
|
||||||
|
someone may actually try to use this on a machine without CPUID.
|
||||||
|
Also for suggesting code for checking this.
|
||||||
|
Robert Dale for pointing out the AMD recognition bug.
|
||||||
|
Jimmy Mayfield and Carl Witty for pointing out the Intel recognition
|
||||||
|
bug.
|
||||||
|
Carl Witty for pointing out the psllq_i2r test bug.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MMX_H
|
||||||
|
#define _MMX_H
|
||||||
|
|
||||||
|
//#define MMX_TRACE
|
||||||
|
|
||||||
|
/* Warning: at this writing, the version of GAS packaged
|
||||||
|
with most Linux distributions does not handle the
|
||||||
|
parallel AND operation mnemonic correctly. If the
|
||||||
|
symbol BROKEN_PAND is defined, a slower alternative
|
||||||
|
coding will be used. If execution of mmxtest results
|
||||||
|
in an illegal instruction fault, define this symbol.
|
||||||
|
*/
|
||||||
|
#undef BROKEN_PAND
|
||||||
|
|
||||||
|
|
||||||
|
/* The type of an value that fits in an MMX register
|
||||||
|
(note that long long constant values MUST be suffixed
|
||||||
|
by LL and unsigned long long values by ULL, lest
|
||||||
|
they be truncated by the compiler)
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
long long q; /* Quadword (64-bit) value */
|
||||||
|
unsigned long long uq; /* Unsigned Quadword */
|
||||||
|
int d[2]; /* 2 Doubleword (32-bit) values */
|
||||||
|
unsigned int ud[2]; /* 2 Unsigned Doubleword */
|
||||||
|
short w[4]; /* 4 Word (16-bit) values */
|
||||||
|
unsigned short uw[4]; /* 4 Unsigned Word */
|
||||||
|
char b[8]; /* 8 Byte (8-bit) values */
|
||||||
|
unsigned char ub[8]; /* 8 Unsigned Byte */
|
||||||
|
float s[2]; /* Single-precision (32-bit) value */
|
||||||
|
} mmx_t;
|
||||||
|
|
||||||
|
/* Helper functions for the instruction macros that follow...
|
||||||
|
(note that memory-to-register, m2r, instructions are nearly
|
||||||
|
as efficient as register-to-register, r2r, instructions;
|
||||||
|
however, memory-to-memory instructions are really simulated
|
||||||
|
as a convenience, and are only 1/3 as efficient)
|
||||||
|
*/
|
||||||
|
#ifdef MMX_TRACE
|
||||||
|
|
||||||
|
/* Include the stuff for printing a trace to stderr...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define mmx_i2r(op, imm, reg) \
|
||||||
|
{ \
|
||||||
|
mmx_t mmx_trace; \
|
||||||
|
mmx_trace = (imm); \
|
||||||
|
fprintf(stderr, #op "_i2r(" #imm "=0x%016llx, ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||||
|
: /* nothing */ \
|
||||||
|
: "X" (imm)); \
|
||||||
|
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define mmx_m2r(op, mem, reg) \
|
||||||
|
{ \
|
||||||
|
mmx_t mmx_trace; \
|
||||||
|
mmx_trace = (mem); \
|
||||||
|
fprintf(stderr, #op "_m2r(" #mem "=0x%016llx, ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||||
|
: /* nothing */ \
|
||||||
|
: "X" (mem)); \
|
||||||
|
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define mmx_r2m(op, reg, mem) \
|
||||||
|
{ \
|
||||||
|
mmx_t mmx_trace; \
|
||||||
|
__asm__ __volatile__ ("movq %%" #reg ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #op "_r2m(" #reg "=0x%016llx, ", mmx_trace.q); \
|
||||||
|
mmx_trace = (mem); \
|
||||||
|
fprintf(stderr, #mem "=0x%016llx) => ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ (#op " %%" #reg ", %0" \
|
||||||
|
: "=X" (mem) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
mmx_trace = (mem); \
|
||||||
|
fprintf(stderr, #mem "=0x%016llx\n", mmx_trace.q); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define mmx_r2r(op, regs, regd) \
|
||||||
|
{ \
|
||||||
|
mmx_t mmx_trace; \
|
||||||
|
__asm__ __volatile__ ("movq %%" #regs ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #op "_r2r(" #regs "=0x%016llx, ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ ("movq %%" #regd ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #regd "=0x%016llx) => ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ (#op " %" #regs ", %" #regd); \
|
||||||
|
__asm__ __volatile__ ("movq %%" #regd ", %0" \
|
||||||
|
: "=X" (mmx_trace) \
|
||||||
|
: /* nothing */ ); \
|
||||||
|
fprintf(stderr, #regd "=0x%016llx\n", mmx_trace.q); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define mmx_m2m(op, mems, memd) \
|
||||||
|
{ \
|
||||||
|
mmx_t mmx_trace; \
|
||||||
|
mmx_trace = (mems); \
|
||||||
|
fprintf(stderr, #op "_m2m(" #mems "=0x%016llx, ", mmx_trace.q); \
|
||||||
|
mmx_trace = (memd); \
|
||||||
|
fprintf(stderr, #memd "=0x%016llx) => ", mmx_trace.q); \
|
||||||
|
__asm__ __volatile__ ("movq %0, %%mm0\n\t" \
|
||||||
|
#op " %1, %%mm0\n\t" \
|
||||||
|
"movq %%mm0, %0" \
|
||||||
|
: "=X" (memd) \
|
||||||
|
: "X" (mems)); \
|
||||||
|
mmx_trace = (memd); \
|
||||||
|
fprintf(stderr, #memd "=0x%016llx\n", mmx_trace.q); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* These macros are a lot simpler without the tracing...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define mmx_i2r(op, imm, reg) \
|
||||||
|
__asm__ __volatile__ (#op " $" #imm ", %%" #reg \
|
||||||
|
: /* nothing */ \
|
||||||
|
: /* nothing */);
|
||||||
|
|
||||||
|
#define mmx_m2r(op, mem, reg) \
|
||||||
|
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||||
|
: /* nothing */ \
|
||||||
|
: "X" (mem))
|
||||||
|
|
||||||
|
#define mmx_r2m(op, reg, mem) \
|
||||||
|
__asm__ __volatile__ (#op " %%" #reg ", %0" \
|
||||||
|
: "=X" (mem) \
|
||||||
|
: /* nothing */ )
|
||||||
|
|
||||||
|
#define mmx_r2r(op, regs, regd) \
|
||||||
|
__asm__ __volatile__ (#op " %" #regs ", %" #regd)
|
||||||
|
|
||||||
|
#define mmx_m2m(op, mems, memd) \
|
||||||
|
__asm__ __volatile__ ("movq %0, %%mm0\n\t" \
|
||||||
|
#op " %1, %%mm0\n\t" \
|
||||||
|
"movq %%mm0, %0" \
|
||||||
|
: "=X" (memd) \
|
||||||
|
: "X" (mems))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x64 MOVe Quadword
|
||||||
|
(this is both a load and a store...
|
||||||
|
in fact, it is the only way to store)
|
||||||
|
*/
|
||||||
|
#define movq_m2r(var, reg) mmx_m2r(movq, var, reg)
|
||||||
|
#define movq_r2m(reg, var) mmx_r2m(movq, reg, var)
|
||||||
|
#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd)
|
||||||
|
#define movq(vars, vard) \
|
||||||
|
__asm__ __volatile__ ("movq %1, %%mm0\n\t" \
|
||||||
|
"movq %%mm0, %0" \
|
||||||
|
: "=X" (vard) \
|
||||||
|
: "X" (vars))
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x32 MOVe Doubleword
|
||||||
|
(like movq, this is both load and store...
|
||||||
|
but is most useful for moving things between
|
||||||
|
mmx registers and ordinary registers)
|
||||||
|
*/
|
||||||
|
#define movd_m2r(var, reg) mmx_m2r(movd, var, reg)
|
||||||
|
#define movd_r2m(reg, var) mmx_r2m(movd, reg, var)
|
||||||
|
#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd)
|
||||||
|
#define movd(vars, vard) \
|
||||||
|
__asm__ __volatile__ ("movd %1, %%mm0\n\t" \
|
||||||
|
"movd %%mm0, %0" \
|
||||||
|
: "=X" (vard) \
|
||||||
|
: "X" (vars))
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32, 4x16, and 8x8 Parallel ADDs
|
||||||
|
*/
|
||||||
|
#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg)
|
||||||
|
#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd)
|
||||||
|
#define paddd(vars, vard) mmx_m2m(paddd, vars, vard)
|
||||||
|
|
||||||
|
#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg)
|
||||||
|
#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd)
|
||||||
|
#define paddw(vars, vard) mmx_m2m(paddw, vars, vard)
|
||||||
|
|
||||||
|
#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg)
|
||||||
|
#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd)
|
||||||
|
#define paddb(vars, vard) mmx_m2m(paddb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic
|
||||||
|
*/
|
||||||
|
#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg)
|
||||||
|
#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd)
|
||||||
|
#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard)
|
||||||
|
|
||||||
|
#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg)
|
||||||
|
#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd)
|
||||||
|
#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
|
||||||
|
*/
|
||||||
|
#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg)
|
||||||
|
#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd)
|
||||||
|
#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard)
|
||||||
|
|
||||||
|
#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg)
|
||||||
|
#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd)
|
||||||
|
#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32, 4x16, and 8x8 Parallel SUBs
|
||||||
|
*/
|
||||||
|
#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg)
|
||||||
|
#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd)
|
||||||
|
#define psubd(vars, vard) mmx_m2m(psubd, vars, vard)
|
||||||
|
|
||||||
|
#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg)
|
||||||
|
#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd)
|
||||||
|
#define psubw(vars, vard) mmx_m2m(psubw, vars, vard)
|
||||||
|
|
||||||
|
#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg)
|
||||||
|
#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd)
|
||||||
|
#define psubb(vars, vard) mmx_m2m(psubb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic
|
||||||
|
*/
|
||||||
|
#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg)
|
||||||
|
#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd)
|
||||||
|
#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard)
|
||||||
|
|
||||||
|
#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg)
|
||||||
|
#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd)
|
||||||
|
#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
|
||||||
|
*/
|
||||||
|
#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg)
|
||||||
|
#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd)
|
||||||
|
#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard)
|
||||||
|
|
||||||
|
#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg)
|
||||||
|
#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd)
|
||||||
|
#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16 Parallel MULs giving Low 4x16 portions of results
|
||||||
|
*/
|
||||||
|
#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg)
|
||||||
|
#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd)
|
||||||
|
#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16 Parallel MULs giving High 4x16 portions of results
|
||||||
|
*/
|
||||||
|
#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg)
|
||||||
|
#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd)
|
||||||
|
#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16->2x32 Parallel Mul-ADD
|
||||||
|
(muls like pmullw, then adds adjacent 16-bit fields
|
||||||
|
in the multiply result to make the final 2x32 result)
|
||||||
|
*/
|
||||||
|
#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg)
|
||||||
|
#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd)
|
||||||
|
#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x64 bitwise AND
|
||||||
|
*/
|
||||||
|
#ifdef BROKEN_PAND
|
||||||
|
#define pand_m2r(var, reg) \
|
||||||
|
{ \
|
||||||
|
mmx_m2r(pandn, (mmx_t) -1LL, reg); \
|
||||||
|
mmx_m2r(pandn, var, reg); \
|
||||||
|
}
|
||||||
|
#define pand_r2r(regs, regd) \
|
||||||
|
{ \
|
||||||
|
mmx_m2r(pandn, (mmx_t) -1LL, regd); \
|
||||||
|
mmx_r2r(pandn, regs, regd) \
|
||||||
|
}
|
||||||
|
#define pand(vars, vard) \
|
||||||
|
{ \
|
||||||
|
movq_m2r(vard, mm0); \
|
||||||
|
mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
|
||||||
|
mmx_m2r(pandn, vars, mm0); \
|
||||||
|
movq_r2m(mm0, vard); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define pand_m2r(var, reg) mmx_m2r(pand, var, reg)
|
||||||
|
#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd)
|
||||||
|
#define pand(vars, vard) mmx_m2m(pand, vars, vard)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x64 bitwise AND with Not the destination
|
||||||
|
*/
|
||||||
|
#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg)
|
||||||
|
#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd)
|
||||||
|
#define pandn(vars, vard) mmx_m2m(pandn, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x64 bitwise OR
|
||||||
|
*/
|
||||||
|
#define por_m2r(var, reg) mmx_m2r(por, var, reg)
|
||||||
|
#define por_r2r(regs, regd) mmx_r2r(por, regs, regd)
|
||||||
|
#define por(vars, vard) mmx_m2m(por, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x64 bitwise eXclusive OR
|
||||||
|
*/
|
||||||
|
#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg)
|
||||||
|
#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd)
|
||||||
|
#define pxor(vars, vard) mmx_m2m(pxor, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
|
||||||
|
(resulting fields are either 0 or -1)
|
||||||
|
*/
|
||||||
|
#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg)
|
||||||
|
#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd)
|
||||||
|
#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard)
|
||||||
|
|
||||||
|
#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg)
|
||||||
|
#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd)
|
||||||
|
#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard)
|
||||||
|
|
||||||
|
#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg)
|
||||||
|
#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd)
|
||||||
|
#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
|
||||||
|
(resulting fields are either 0 or -1)
|
||||||
|
*/
|
||||||
|
#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg)
|
||||||
|
#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd)
|
||||||
|
#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard)
|
||||||
|
|
||||||
|
#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg)
|
||||||
|
#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd)
|
||||||
|
#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard)
|
||||||
|
|
||||||
|
#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg)
|
||||||
|
#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd)
|
||||||
|
#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical
|
||||||
|
*/
|
||||||
|
#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg)
|
||||||
|
#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg)
|
||||||
|
#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd)
|
||||||
|
#define psllq(vars, vard) mmx_m2m(psllq, vars, vard)
|
||||||
|
|
||||||
|
#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg)
|
||||||
|
#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg)
|
||||||
|
#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd)
|
||||||
|
#define pslld(vars, vard) mmx_m2m(pslld, vars, vard)
|
||||||
|
|
||||||
|
#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg)
|
||||||
|
#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg)
|
||||||
|
#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd)
|
||||||
|
#define psllw(vars, vard) mmx_m2m(psllw, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical
|
||||||
|
*/
|
||||||
|
#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg)
|
||||||
|
#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg)
|
||||||
|
#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd)
|
||||||
|
#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard)
|
||||||
|
|
||||||
|
#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg)
|
||||||
|
#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg)
|
||||||
|
#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd)
|
||||||
|
#define psrld(vars, vard) mmx_m2m(psrld, vars, vard)
|
||||||
|
|
||||||
|
#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg)
|
||||||
|
#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg)
|
||||||
|
#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd)
|
||||||
|
#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32 and 4x16 Parallel Shift Right Arithmetic
|
||||||
|
*/
|
||||||
|
#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg)
|
||||||
|
#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg)
|
||||||
|
#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd)
|
||||||
|
#define psrad(vars, vard) mmx_m2m(psrad, vars, vard)
|
||||||
|
|
||||||
|
#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg)
|
||||||
|
#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg)
|
||||||
|
#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd)
|
||||||
|
#define psraw(vars, vard) mmx_m2m(psraw, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
|
||||||
|
(packs source and dest fields into dest in that order)
|
||||||
|
*/
|
||||||
|
#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg)
|
||||||
|
#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
|
||||||
|
#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard)
|
||||||
|
|
||||||
|
#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg)
|
||||||
|
#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
|
||||||
|
#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 4x16->8x8 PACK and Unsigned Saturate
|
||||||
|
(packs source and dest fields into dest in that order)
|
||||||
|
*/
|
||||||
|
#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg)
|
||||||
|
#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
|
||||||
|
#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
|
||||||
|
(interleaves low half of dest with low half of source
|
||||||
|
as padding in each result field)
|
||||||
|
*/
|
||||||
|
#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg)
|
||||||
|
#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
|
||||||
|
#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard)
|
||||||
|
|
||||||
|
#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg)
|
||||||
|
#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
|
||||||
|
#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard)
|
||||||
|
|
||||||
|
#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg)
|
||||||
|
#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
|
||||||
|
#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
|
||||||
|
(interleaves high half of dest with high half of source
|
||||||
|
as padding in each result field)
|
||||||
|
*/
|
||||||
|
#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg)
|
||||||
|
#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
|
||||||
|
#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard)
|
||||||
|
|
||||||
|
#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg)
|
||||||
|
#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
|
||||||
|
#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard)
|
||||||
|
|
||||||
|
#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg)
|
||||||
|
#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
|
||||||
|
#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard)
|
||||||
|
|
||||||
|
|
||||||
|
/* Empty MMx State
|
||||||
|
(used to clean-up when going from mmx to float use
|
||||||
|
of the registers that are shared by both; note that
|
||||||
|
there is no float-to-mmx operation needed, because
|
||||||
|
only the float tag word info is corruptible)
|
||||||
|
*/
|
||||||
|
#ifdef MMX_TRACE
|
||||||
|
|
||||||
|
#define emms() \
|
||||||
|
{ \
|
||||||
|
fprintf(stderr, "emms()\n"); \
|
||||||
|
__asm__ __volatile__ ("emms"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define emms() __asm__ __volatile__ ("emms")
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,259 @@
|
||||||
|
#ifndef DBG
|
||||||
|
#define DBG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_WRITE_LOCK
|
||||||
|
#define HW_WRITE_LOCK() HW_LOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_WRITE_UNLOCK
|
||||||
|
#define HW_WRITE_UNLOCK() HW_UNLOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_READ_LOCK
|
||||||
|
#define HW_READ_LOCK() HW_LOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_READ_UNLOCK
|
||||||
|
#define HW_READ_UNLOCK() HW_UNLOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_READ_CLIPLOOP
|
||||||
|
#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_WRITE_CLIPLOOP
|
||||||
|
#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void TAG(WriteRGBASpan)( const GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
const GLubyte rgba[][4],
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1;
|
||||||
|
GLint n1;
|
||||||
|
LOCAL_VARS;
|
||||||
|
|
||||||
|
y = Y_FLIP(y);
|
||||||
|
|
||||||
|
HW_WRITE_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN(x,y,n,x1,n1,i);
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
|
||||||
|
(int)i, (int)n1, (int)x1);
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
{
|
||||||
|
for (;n1>0;i++,x1++,n1--)
|
||||||
|
if (mask[i])
|
||||||
|
WRITE_RGBA( x1, y,
|
||||||
|
rgba[i][0], rgba[i][1],
|
||||||
|
rgba[i][2], rgba[i][3] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (;n1>0;i++,x1++,n1--)
|
||||||
|
WRITE_RGBA( x1, y,
|
||||||
|
rgba[i][0], rgba[i][1],
|
||||||
|
rgba[i][2], rgba[i][3] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TAG(WriteRGBSpan)( const GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
const GLubyte rgb[][3],
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1;
|
||||||
|
GLint n1;
|
||||||
|
LOCAL_VARS;
|
||||||
|
|
||||||
|
y = Y_FLIP(y);
|
||||||
|
|
||||||
|
HW_WRITE_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN(x,y,n,x1,n1,i);
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
|
||||||
|
(int)i, (int)n1, (int)x1);
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
{
|
||||||
|
for (;n1>0;i++,x1++,n1--)
|
||||||
|
if (mask[i])
|
||||||
|
WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (;n1>0;i++,x1++,n1--)
|
||||||
|
WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TAG(WriteRGBAPixels)( const GLcontext *ctx,
|
||||||
|
GLuint n,
|
||||||
|
const GLint x[],
|
||||||
|
const GLint y[],
|
||||||
|
const GLubyte rgba[][4],
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
LOCAL_VARS;
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
|
||||||
|
|
||||||
|
HW_WRITE_CLIPLOOP()
|
||||||
|
{
|
||||||
|
for (i=0;i<n;i++)
|
||||||
|
{
|
||||||
|
if (mask[i]) {
|
||||||
|
const int fy = Y_FLIP(y[i]);
|
||||||
|
if (CLIPPIXEL(x[i],fy))
|
||||||
|
WRITE_RGBA( x[i], fy,
|
||||||
|
rgba[i][0], rgba[i][1],
|
||||||
|
rgba[i][2], rgba[i][3] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void TAG(WriteMonoRGBASpan)( const GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
const GLchan color[4],
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1;
|
||||||
|
GLint n1;
|
||||||
|
LOCAL_VARS;
|
||||||
|
INIT_MONO_PIXEL(p, color);
|
||||||
|
|
||||||
|
y = Y_FLIP( y );
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
|
||||||
|
|
||||||
|
HW_WRITE_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN(x,y,n,x1,n1,i);
|
||||||
|
for (;n1>0;i++,x1++,n1--)
|
||||||
|
if (mask[i])
|
||||||
|
WRITE_PIXEL( x1, y, p );
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void TAG(WriteMonoRGBAPixels)( const GLcontext *ctx,
|
||||||
|
GLuint n,
|
||||||
|
const GLint x[], const GLint y[],
|
||||||
|
const GLchan color[],
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
LOCAL_VARS;
|
||||||
|
INIT_MONO_PIXEL(p, color);
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
|
||||||
|
|
||||||
|
HW_WRITE_CLIPLOOP()
|
||||||
|
{
|
||||||
|
for (i=0;i<n;i++)
|
||||||
|
if (mask[i]) {
|
||||||
|
int fy = Y_FLIP(y[i]);
|
||||||
|
if (CLIPPIXEL( x[i], fy ))
|
||||||
|
WRITE_PIXEL( x[i], fy, p );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void TAG(ReadRGBASpan)( const GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
GLubyte rgba[][4])
|
||||||
|
{
|
||||||
|
HW_READ_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1,n1;
|
||||||
|
LOCAL_VARS;
|
||||||
|
|
||||||
|
y = Y_FLIP(y);
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "ReadRGBASpan\n");
|
||||||
|
|
||||||
|
HW_READ_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN(x,y,n,x1,n1,i);
|
||||||
|
for (;n1>0;i++,x1++,n1--)
|
||||||
|
READ_RGBA( rgba[i], x1, y );
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_READ_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void TAG(ReadRGBAPixels)( const GLcontext *ctx,
|
||||||
|
GLuint n, const GLint x[], const GLint y[],
|
||||||
|
GLubyte rgba[][4], const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_READ_LOCK()
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
LOCAL_VARS;
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
|
||||||
|
|
||||||
|
HW_READ_CLIPLOOP()
|
||||||
|
{
|
||||||
|
for (i=0;i<n;i++)
|
||||||
|
if (mask[i]) {
|
||||||
|
int fy = Y_FLIP( y[i] );
|
||||||
|
if (CLIPPIXEL( x[i], fy ))
|
||||||
|
READ_RGBA( rgba[i], x[i], fy );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_READ_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#undef WRITE_PIXEL
|
||||||
|
#undef WRITE_RGBA
|
||||||
|
#undef READ_RGBA
|
||||||
|
#undef TAG
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* $XFree86: xc/lib/GL/mesa/src/drv/common/stenciltmp.h,v 1.3 2001/03/21 16:14:20 dawes Exp $ */
|
||||||
|
|
||||||
|
#ifndef DBG
|
||||||
|
#define DBG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_WRITE_LOCK
|
||||||
|
#define HW_WRITE_LOCK() HW_LOCK()
|
||||||
|
#endif
|
||||||
|
#ifndef HW_WRITE_UNLOCK
|
||||||
|
#define HW_WRITE_UNLOCK() HW_UNLOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HW_READ_LOCK
|
||||||
|
#define HW_READ_LOCK() HW_LOCK()
|
||||||
|
#endif
|
||||||
|
#ifndef HW_READ_UNLOCK
|
||||||
|
#define HW_READ_UNLOCK() HW_UNLOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void TAG(WriteStencilSpan)( GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
const GLstencil *stencil,
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1;
|
||||||
|
GLint n1;
|
||||||
|
LOCAL_STENCIL_VARS;
|
||||||
|
|
||||||
|
y = Y_FLIP(y);
|
||||||
|
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN(x,y,n,x1,n1,i);
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
|
||||||
|
(int)i, (int)n1, (int)x1);
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
{
|
||||||
|
for (;i<n1;i++,x1++)
|
||||||
|
if (mask[i])
|
||||||
|
WRITE_STENCIL( x1, y, stencil[i] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (;i<n1;i++,x1++)
|
||||||
|
WRITE_STENCIL( x1, y, stencil[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void TAG(WriteStencilPixels)( GLcontext *ctx,
|
||||||
|
GLuint n,
|
||||||
|
const GLint x[],
|
||||||
|
const GLint y[],
|
||||||
|
const GLstencil stencil[],
|
||||||
|
const GLubyte mask[] )
|
||||||
|
{
|
||||||
|
HW_WRITE_LOCK()
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
LOCAL_STENCIL_VARS;
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "WriteStencilPixels\n");
|
||||||
|
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
for (i=0;i<n;i++)
|
||||||
|
{
|
||||||
|
if (mask[i]) {
|
||||||
|
const int fy = Y_FLIP(y[i]);
|
||||||
|
if (CLIPPIXEL(x[i],fy))
|
||||||
|
WRITE_STENCIL( x[i], fy, stencil[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_WRITE_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read stencil spans and pixels
|
||||||
|
*/
|
||||||
|
static void TAG(ReadStencilSpan)( GLcontext *ctx,
|
||||||
|
GLuint n, GLint x, GLint y,
|
||||||
|
GLstencil stencil[])
|
||||||
|
{
|
||||||
|
HW_READ_LOCK()
|
||||||
|
{
|
||||||
|
GLint x1,n1;
|
||||||
|
LOCAL_STENCIL_VARS;
|
||||||
|
|
||||||
|
y = Y_FLIP(y);
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "ReadStencilSpan\n");
|
||||||
|
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
GLint i = 0;
|
||||||
|
CLIPSPAN(x,y,n,x1,n1,i);
|
||||||
|
for (;i<n1;i++)
|
||||||
|
READ_STENCIL( stencil[i], (x1+i), y );
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_READ_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TAG(ReadStencilPixels)( GLcontext *ctx, GLuint n,
|
||||||
|
const GLint x[], const GLint y[],
|
||||||
|
GLstencil stencil[] )
|
||||||
|
{
|
||||||
|
HW_READ_LOCK()
|
||||||
|
{
|
||||||
|
GLint i;
|
||||||
|
LOCAL_STENCIL_VARS;
|
||||||
|
|
||||||
|
if (DBG) fprintf(stderr, "ReadStencilPixels\n");
|
||||||
|
|
||||||
|
HW_CLIPLOOP()
|
||||||
|
{
|
||||||
|
for (i=0;i<n;i++) {
|
||||||
|
int fy = Y_FLIP( y[i] );
|
||||||
|
if (CLIPPIXEL( x[i], fy ))
|
||||||
|
READ_STENCIL( stencil[i], x[i], fy );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HW_ENDCLIPLOOP();
|
||||||
|
}
|
||||||
|
HW_READ_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#undef WRITE_STENCIL
|
||||||
|
#undef READ_STENCIL
|
||||||
|
#undef TAG
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,293 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2000-2001 VA Linux Systems, Inc.
|
||||||
|
* (c) Copyright IBM Corporation 2002
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ian Romanick <idr@us.ibm.com>
|
||||||
|
* Keith Whitwell <keithw@tungstengraphics.com>
|
||||||
|
* Kevin E. Martin <kem@users.sourceforge.net>
|
||||||
|
* Gareth Hughes <gareth@nvidia.com>
|
||||||
|
*/
|
||||||
|
/* $XFree86:$ */
|
||||||
|
|
||||||
|
/** \file texmem.h
|
||||||
|
* Public interface to the DRI texture memory management routines.
|
||||||
|
*
|
||||||
|
* \sa texmem.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRI_TEXMEM_H
|
||||||
|
#define DRI_TEXMEM_H
|
||||||
|
|
||||||
|
#include "mtypes.h"
|
||||||
|
#include "mm.h"
|
||||||
|
#include "xf86drm.h"
|
||||||
|
|
||||||
|
struct dri_tex_heap;
|
||||||
|
typedef struct dri_tex_heap driTexHeap;
|
||||||
|
|
||||||
|
struct dri_texture_object;
|
||||||
|
typedef struct dri_texture_object driTextureObject;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base texture object type. Each driver will extend this type with its own
|
||||||
|
* private data members.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct dri_texture_object {
|
||||||
|
struct dri_texture_object * next;
|
||||||
|
struct dri_texture_object * prev;
|
||||||
|
|
||||||
|
driTexHeap * heap; /**< Texture heap currently stored in */
|
||||||
|
struct gl_texture_object * tObj;/**< Pointer to Mesa texture object
|
||||||
|
* If NULL, this texture object is a
|
||||||
|
* "placeholder" object representing
|
||||||
|
* texture memory in use by another context.
|
||||||
|
* A placeholder should have a heap and a memBlock.
|
||||||
|
*/
|
||||||
|
PMemBlock memBlock; /**< Memory block containing texture */
|
||||||
|
unsigned bound; /**< Texture unit currently bound to */
|
||||||
|
|
||||||
|
unsigned totalSize; /**< Total size of the texture,
|
||||||
|
* including all mipmap levels
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned dirty_images[6]; /**< Flags for whether or not images
|
||||||
|
* need to be uploaded to local or
|
||||||
|
* AGP texture space. One flag set
|
||||||
|
* for each cube face for cubic
|
||||||
|
* textures. Bit zero corresponds to
|
||||||
|
* the base-level, which may or may
|
||||||
|
* not be the level zero mipmap.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned timestamp; /**< Timestamp used to
|
||||||
|
* synchronize with 3d engine
|
||||||
|
* in hardware where textures
|
||||||
|
* are uploaded directly to
|
||||||
|
* the framebuffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned firstLevel; /**< Image in \c tObj->Image that
|
||||||
|
* corresponds to the base-level of
|
||||||
|
* this texture object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned lastLevel; /**< Last image in \c tObj->Image used
|
||||||
|
* by the current LOD settings of this
|
||||||
|
* texture object. This value must be
|
||||||
|
* greater than or equal to
|
||||||
|
* \c firstLevel.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (destroy_texture_object_t)( void * driverContext,
|
||||||
|
driTextureObject * t );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client-private representation of texture memory state.
|
||||||
|
*
|
||||||
|
* Clients will place one or more of these structs in their driver
|
||||||
|
* context struct to manage one or more global texture heaps.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct dri_tex_heap {
|
||||||
|
|
||||||
|
/** Client-supplied heap identifier
|
||||||
|
*/
|
||||||
|
unsigned heapId;
|
||||||
|
|
||||||
|
/** Pointer to the client's private context
|
||||||
|
*/
|
||||||
|
void *driverContext;
|
||||||
|
|
||||||
|
/** Total size of the heap, in bytes
|
||||||
|
*/
|
||||||
|
unsigned size;
|
||||||
|
|
||||||
|
/** \brief \f$log_2\f$ of size of single heap region
|
||||||
|
*
|
||||||
|
* Each context takes memory from the global texture heap in
|
||||||
|
* \f$2^{logGranularity}\f$ byte blocks. The value of
|
||||||
|
* \a logGranularity is based on the amount of memory represented
|
||||||
|
* by the heap and the maximum number of regions in the SAREA. Given
|
||||||
|
* \a b bytes of texture memory an \a n regions in the SAREA,
|
||||||
|
* \a logGranularity will be \f$\lfloor\log_2( b / n )\rfloor\f$.
|
||||||
|
*/
|
||||||
|
unsigned logGranularity;
|
||||||
|
|
||||||
|
/** \brief Required alignment of allocations in this heap
|
||||||
|
*
|
||||||
|
* The alignment shift is supplied to \a mmAllocMem when memory is
|
||||||
|
* allocated from this heap. The value of \a alignmentShift will
|
||||||
|
* typically reflect some require of the hardware. This value has
|
||||||
|
* \b no \b relation to \a logGranularity. \a alignmentShift is a
|
||||||
|
* per-context value.
|
||||||
|
*
|
||||||
|
* \sa mmAllocMem
|
||||||
|
*/
|
||||||
|
unsigned alignmentShift;
|
||||||
|
|
||||||
|
/** Number of elements in global list (the SAREA).
|
||||||
|
*/
|
||||||
|
unsigned nrRegions;
|
||||||
|
|
||||||
|
/** Pointer to SAREA \a driTexRegion array
|
||||||
|
*/
|
||||||
|
drmTextureRegionPtr global_regions;
|
||||||
|
|
||||||
|
/** Pointer to the texture state age (generation number) in the SAREA
|
||||||
|
*/
|
||||||
|
unsigned * global_age;
|
||||||
|
|
||||||
|
/** Local age (generation number) of texture state
|
||||||
|
*/
|
||||||
|
unsigned local_age;
|
||||||
|
|
||||||
|
/** Memory heap used to manage texture memory represented by
|
||||||
|
* this texture heap.
|
||||||
|
*/
|
||||||
|
memHeap_t * memory_heap;
|
||||||
|
|
||||||
|
/** List of objects that we currently believe to be in texture
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
driTextureObject texture_objects;
|
||||||
|
|
||||||
|
/** Pointer to the list of texture objects that are not in
|
||||||
|
* texture memory.
|
||||||
|
*/
|
||||||
|
driTextureObject * swapped_objects;
|
||||||
|
|
||||||
|
/** Size of the driver-speicific texture object.
|
||||||
|
*/
|
||||||
|
unsigned texture_object_size;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Function to destroy driver-specific texture object data.
|
||||||
|
*
|
||||||
|
* This function is supplied by the driver so that the texture manager
|
||||||
|
* can release all resources associated with a texture object. This
|
||||||
|
* function should only release driver-specific data. That is,
|
||||||
|
* \a driDestroyTextureObject will release the texture memory
|
||||||
|
* associated with the texture object, it will release the memory
|
||||||
|
* for the texture object itself, and it will unlink the texture
|
||||||
|
* object from the texture object lists.
|
||||||
|
*
|
||||||
|
* \param driverContext Pointer to the driver supplied context
|
||||||
|
* \param t Texture object that is to be destroyed
|
||||||
|
* \sa driDestroyTextureObject
|
||||||
|
*/
|
||||||
|
|
||||||
|
destroy_texture_object_t * destroy_texture_object;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
unsigned * texture_swaps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp used to synchronize with 3d engine in hardware
|
||||||
|
* where textures are uploaded directly to the
|
||||||
|
* framebuffer.
|
||||||
|
*/
|
||||||
|
unsigned timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the client on lock contention to determine whether textures have
|
||||||
|
* been stolen. If another client has modified a region in which we have
|
||||||
|
* textures, then we need to figure out which of our textures have been
|
||||||
|
* removed and update our global LRU.
|
||||||
|
*
|
||||||
|
* \param heap Texture heap to be updated
|
||||||
|
* \hideinitializer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DRI_AGE_TEXTURES( heap ) \
|
||||||
|
do { \
|
||||||
|
if ( ((heap) != NULL) \
|
||||||
|
&& ((heap)->local_age != (heap)->global_age[0]) ) \
|
||||||
|
driAgeTextures( heap ); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This should be called whenever there has been contention on the hardware
|
||||||
|
* lock. driAgeTextures should not be called directly. Instead, clients
|
||||||
|
* should use DRI_AGE_TEXTURES, above.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void driAgeTextures( driTexHeap * heap );
|
||||||
|
|
||||||
|
void driUpdateTextureLRU( driTextureObject * t );
|
||||||
|
void driSwapOutTextureObject( driTextureObject * t );
|
||||||
|
void driDestroyTextureObject( driTextureObject * t );
|
||||||
|
int driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
|
||||||
|
driTextureObject * t );
|
||||||
|
|
||||||
|
GLboolean driIsTextureResident( GLcontext * ctx,
|
||||||
|
struct gl_texture_object * texObj );
|
||||||
|
|
||||||
|
driTexHeap * driCreateTextureHeap( unsigned heap_id, void * context,
|
||||||
|
unsigned size, unsigned alignmentShift, unsigned nr_regions,
|
||||||
|
drmTextureRegionPtr global_regions, unsigned * global_age,
|
||||||
|
driTextureObject * swapped_objects, unsigned texture_object_size,
|
||||||
|
destroy_texture_object_t * destroy_tex_obj );
|
||||||
|
void driDestroyTextureHeap( driTexHeap * heap );
|
||||||
|
|
||||||
|
void
|
||||||
|
driCalculateMaxTextureLevels( driTexHeap * const * heaps,
|
||||||
|
unsigned nr_heaps,
|
||||||
|
struct gl_constants * limits,
|
||||||
|
unsigned max_bytes_per_texel,
|
||||||
|
unsigned max_2D_size,
|
||||||
|
unsigned max_3D_size,
|
||||||
|
unsigned max_cube_size,
|
||||||
|
unsigned max_rect_size,
|
||||||
|
unsigned mipmaps_at_once,
|
||||||
|
int all_textures_one_heap );
|
||||||
|
|
||||||
|
void
|
||||||
|
driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter );
|
||||||
|
|
||||||
|
#define DRI_TEXMGR_DO_TEXTURE_1D 0x0001
|
||||||
|
#define DRI_TEXMGR_DO_TEXTURE_2D 0x0002
|
||||||
|
#define DRI_TEXMGR_DO_TEXTURE_3D 0x0004
|
||||||
|
#define DRI_TEXMGR_DO_TEXTURE_CUBE 0x0008
|
||||||
|
#define DRI_TEXMGR_DO_TEXTURE_RECT 0x0010
|
||||||
|
|
||||||
|
void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
|
||||||
|
GLuint targets );
|
||||||
|
|
||||||
|
GLboolean driValidateTextureHeaps( driTexHeap * const * texture_heaps,
|
||||||
|
unsigned nr_heaps, const driTextureObject * swapped );
|
||||||
|
|
||||||
|
#endif /* DRI_TEXMEM_H */
|
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
* (c) Copyright IBM Corporation 2002
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ian Romanick <idr@us.ibm.com>
|
||||||
|
*/
|
||||||
|
/* $XFree86:$ */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "mtypes.h"
|
||||||
|
#include "extensions.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#if defined(USE_X86_ASM)
|
||||||
|
#include "X86/common_x86_asm.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
driParseDebugString( const char * debug,
|
||||||
|
const struct dri_debug_control * control )
|
||||||
|
{
|
||||||
|
unsigned flag;
|
||||||
|
|
||||||
|
|
||||||
|
flag = 0;
|
||||||
|
if ( debug != NULL ) {
|
||||||
|
while( control->string != NULL ) {
|
||||||
|
if ( strstr( debug, control->string ) != NULL ) {
|
||||||
|
flag |= control->flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
control++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
driGetRendererString( char * buffer, const char * hardware_name,
|
||||||
|
const char * driver_date, GLuint agp_mode )
|
||||||
|
{
|
||||||
|
#ifdef USE_X86_ASM
|
||||||
|
char * x86_str = "";
|
||||||
|
char * mmx_str = "";
|
||||||
|
char * tdnow_str = "";
|
||||||
|
char * sse_str = "";
|
||||||
|
#endif
|
||||||
|
unsigned offset;
|
||||||
|
|
||||||
|
|
||||||
|
offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
|
||||||
|
|
||||||
|
/* Append any AGP-specific information.
|
||||||
|
*/
|
||||||
|
switch ( agp_mode ) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append any CPU-specific information.
|
||||||
|
*/
|
||||||
|
#ifdef USE_X86_ASM
|
||||||
|
if ( _mesa_x86_cpu_features ) {
|
||||||
|
x86_str = " x86";
|
||||||
|
}
|
||||||
|
# ifdef USE_MMX_ASM
|
||||||
|
if ( cpu_has_mmx ) {
|
||||||
|
mmx_str = (cpu_has_mmxext) ? "/MMX+" : "/MMX";
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# ifdef USE_3DNOW_ASM
|
||||||
|
if ( cpu_has_3dnow ) {
|
||||||
|
tdnow_str = (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!";
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# ifdef USE_SSE_ASM
|
||||||
|
if ( cpu_has_xmm ) {
|
||||||
|
sse_str = (cpu_has_xmm2) ? "/SSE2" : "/SSE";
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
offset += sprintf( & buffer[ offset ], "%s%s%s%s",
|
||||||
|
x86_str, mmx_str, tdnow_str, sse_str );
|
||||||
|
|
||||||
|
#elif defined(USE_SPARC_ASM)
|
||||||
|
|
||||||
|
offset += sprintf( & buffer[ offset ], " Sparc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void driInitExtensions( GLcontext * ctx,
|
||||||
|
const char * const extensions_to_enable[],
|
||||||
|
GLboolean enable_imaging )
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
if ( enable_imaging ) {
|
||||||
|
_mesa_enable_imaging_extensions( ctx );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0 ; extensions_to_enable[i] != NULL ; i++ ) {
|
||||||
|
_mesa_enable_extension( ctx, extensions_to_enable[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLboolean
|
||||||
|
driCheckDriDdxDrmVersions(__DRIscreenPrivate *sPriv,
|
||||||
|
const char * driver_name,
|
||||||
|
int dri_major, int dri_minor,
|
||||||
|
int ddx_major, int ddx_minor,
|
||||||
|
int drm_major, int drm_minor)
|
||||||
|
{
|
||||||
|
static const char format[] = "%s DRI driver expected %s version %d.%d.x "
|
||||||
|
"but got version %d.%d.%d";
|
||||||
|
int major, minor, patch;
|
||||||
|
|
||||||
|
#ifndef _SOLO
|
||||||
|
/* Check the DRI version */
|
||||||
|
if (XF86DRIQueryVersion(sPriv->display, &major, &minor, &patch)) {
|
||||||
|
if (major != dri_major || minor < dri_minor) {
|
||||||
|
__driUtilMessage(format, "DRI", driver_name, dri_major, dri_minor,
|
||||||
|
major, minor, patch);
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)major;(void)minor;(void)patch;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check that the DDX driver version is compatible */
|
||||||
|
if (sPriv->ddxMajor != ddx_major || sPriv->ddxMinor < ddx_minor) {
|
||||||
|
__driUtilMessage(format, "DDX", driver_name, ddx_major, ddx_minor,
|
||||||
|
sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch);
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the DRM driver version is compatible */
|
||||||
|
if (sPriv->drmMajor != drm_major || sPriv->drmMinor < drm_minor) {
|
||||||
|
__driUtilMessage(format, "DRM", driver_name, drm_major, drm_minor,
|
||||||
|
sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch);
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GL_TRUE;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* (c) Copyright IBM Corporation 2002
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ian Romanick <idr@us.ibm.com>
|
||||||
|
*/
|
||||||
|
/* $XFree86:$ */
|
||||||
|
|
||||||
|
#ifndef DRI_DEBUG_H
|
||||||
|
#define DRI_DEBUG_H
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
|
#include "dri_util.h"
|
||||||
|
|
||||||
|
struct dri_debug_control
|
||||||
|
{
|
||||||
|
const char * string;
|
||||||
|
unsigned flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern unsigned driParseDebugString( const char * debug,
|
||||||
|
const struct dri_debug_control * control );
|
||||||
|
|
||||||
|
extern unsigned driGetRendererString( char * buffer,
|
||||||
|
const char * hardware_name, const char * driver_date, GLuint agp_mode );
|
||||||
|
|
||||||
|
extern void driInitExtensions( GLcontext * ctx,
|
||||||
|
const char * const card_extensions[], GLboolean enable_imaging );
|
||||||
|
|
||||||
|
extern GLboolean driCheckDriDdxDrmVersions( __DRIscreenPrivate *sPriv,
|
||||||
|
const char * driver_name, int dri_major, int dri_minor,
|
||||||
|
int ddx_major, int ddx_minor, int drm_major, int drm_minor );
|
||||||
|
|
||||||
|
#endif /* DRI_DEBUG_H */
|
|
@ -0,0 +1,325 @@
|
||||||
|
/* -*- mode: c; c-basic-offset: 3 -*- */
|
||||||
|
/*
|
||||||
|
* (c) Copyright IBM Corporation 2002
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ian Romanick <idr@us.ibm.com>
|
||||||
|
*/
|
||||||
|
/* $XFree86:$ */
|
||||||
|
|
||||||
|
#include "glheader.h"
|
||||||
|
#include "xf86drm.h"
|
||||||
|
#include "mtypes.h"
|
||||||
|
#include "macros.h"
|
||||||
|
#include "dd.h"
|
||||||
|
#include "vblank.h"
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* Get the current MSC refresh counter.
|
||||||
|
*
|
||||||
|
* Stores the 64-bit count of vertical refreshes since some (arbitrary)
|
||||||
|
* point in time in \c count. Unless the value wraps around, which it
|
||||||
|
* may, it will never decrease.
|
||||||
|
*
|
||||||
|
* \warning This function is called from \c glXGetVideoSyncSGI, which expects
|
||||||
|
* a \c count of type \c unsigned (32-bit), and \c glXGetSyncValuesOML, which
|
||||||
|
* expects a \c count of type \c int64_t (signed 64-bit). The kernel ioctl
|
||||||
|
* currently always returns a \c sequence of type \c unsigned.
|
||||||
|
*
|
||||||
|
* \param priv Pointer to the DRI screen private struct.
|
||||||
|
* \param count Storage to hold MSC counter.
|
||||||
|
* \return Zero is returned on success. A negative errno value
|
||||||
|
* is returned on failure.
|
||||||
|
*/
|
||||||
|
int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count )
|
||||||
|
{
|
||||||
|
drmVBlank vbl;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Don't wait for anything. Just get the current refresh count. */
|
||||||
|
|
||||||
|
vbl.request.type = DRM_VBLANK_RELATIVE;
|
||||||
|
vbl.request.sequence = 0;
|
||||||
|
|
||||||
|
ret = drmWaitVBlank( priv->fd, &vbl );
|
||||||
|
*count = (int64_t)vbl.reply.sequence;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* Wait for a specified refresh count. This implements most of the
|
||||||
|
* functionality of \c glXWaitForMscOML from the GLX_OML_sync_control spec.
|
||||||
|
* Waits for the \c target_msc refresh. If that has already passed, it
|
||||||
|
* waits until \f$(MSC \bmod divisor)\f$ is equal to \c remainder. If
|
||||||
|
* \c target_msc is 0, use the behavior of glXWaitVideoSyncSGI(), which
|
||||||
|
* omits the initial check against a target MSC value.
|
||||||
|
*
|
||||||
|
* This function is actually something of a hack. The problem is that, at
|
||||||
|
* the time of this writing, none of the existing DRM modules support an
|
||||||
|
* ioctl that returns a 64-bit count (at least not on 32-bit platforms).
|
||||||
|
* However, this function exists to support a GLX function that requires
|
||||||
|
* the use of 64-bit counts. As such, there is a little bit of ugly
|
||||||
|
* hackery at the end of this function to make the 32-bit count act like
|
||||||
|
* a 64-bit count. There are still some cases where this will break, but
|
||||||
|
* I believe it catches the most common cases.
|
||||||
|
*
|
||||||
|
* The real solution is to provide an ioctl that uses a 64-bit count.
|
||||||
|
*
|
||||||
|
* \param dpy Pointer to the \c Display.
|
||||||
|
* \param priv Pointer to the DRI drawable private.
|
||||||
|
* \param target_msc Desired refresh count to wait for. A value of 0
|
||||||
|
* means to use the glXWaitVideoSyncSGI() behavior.
|
||||||
|
* \param divisor MSC divisor if \c target_msc is already reached.
|
||||||
|
* \param remainder Desired MSC remainder if \c target_msc is already
|
||||||
|
* reached.
|
||||||
|
* \param msc Buffer to hold MSC when done waiting.
|
||||||
|
*
|
||||||
|
* \return Zero on success or \c GLX_BAD_CONTEXT on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int driWaitForMSC32( __DRIdrawablePrivate *priv,
|
||||||
|
int64_t target_msc, int64_t divisor, int64_t remainder,
|
||||||
|
int64_t * msc )
|
||||||
|
{
|
||||||
|
drmVBlank vbl;
|
||||||
|
|
||||||
|
|
||||||
|
if ( divisor != 0 ) {
|
||||||
|
unsigned int target = (unsigned int)target_msc;
|
||||||
|
unsigned int next = target;
|
||||||
|
unsigned int r;
|
||||||
|
int dont_wait = (target_msc == 0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* dont_wait means we're using the glXWaitVideoSyncSGI() behavior.
|
||||||
|
* The first time around, just get the current count and proceed
|
||||||
|
* to the test for (MSC % divisor) == remainder.
|
||||||
|
*/
|
||||||
|
vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE :
|
||||||
|
DRM_VBLANK_ABSOLUTE;
|
||||||
|
vbl.request.sequence = next;
|
||||||
|
|
||||||
|
if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
|
||||||
|
/* FIXME: This doesn't seem like the right thing to return here.
|
||||||
|
*/
|
||||||
|
#ifndef _SOLO
|
||||||
|
return GLX_BAD_CONTEXT;
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
dont_wait = 0;
|
||||||
|
if (target_msc != 0 && vbl.reply.sequence == target)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Assuming the wait-done test fails, the next refresh to wait for
|
||||||
|
* will be one that satisfies (MSC % divisor) == remainder. The
|
||||||
|
* value (MSC - (MSC % divisor) + remainder) is the refresh value
|
||||||
|
* closest to the current value that would satisfy the equation.
|
||||||
|
* If this refresh has already happened, we add divisor to obtain
|
||||||
|
* the next refresh after the current one that will satisfy it.
|
||||||
|
*/
|
||||||
|
r = (vbl.reply.sequence % (unsigned int)divisor);
|
||||||
|
next = (vbl.reply.sequence - r + (unsigned int)remainder);
|
||||||
|
if (next <= vbl.reply.sequence) next += (unsigned int)divisor;
|
||||||
|
|
||||||
|
} while ( r != (unsigned int)remainder );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* If the \c divisor is zero, just wait until the MSC is greater
|
||||||
|
* than or equal to \c target_msc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
vbl.request.type = DRM_VBLANK_ABSOLUTE;
|
||||||
|
vbl.request.sequence = target_msc;
|
||||||
|
|
||||||
|
if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
|
||||||
|
/* FIXME: This doesn't seem like the right thing to return here.
|
||||||
|
*/
|
||||||
|
#ifndef _SOLO
|
||||||
|
return GLX_BAD_CONTEXT;
|
||||||
|
#else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*msc = (target_msc & 0xffffffff00000000LL);
|
||||||
|
*msc |= vbl.reply.sequence;
|
||||||
|
if ( *msc < target_msc ) {
|
||||||
|
*msc += 0x0000000100000000LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* Gets a set of default vertical-blank-wait flags based on the internal GLX
|
||||||
|
* API version and several environment variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLuint driGetDefaultVBlankFlags( void )
|
||||||
|
{
|
||||||
|
GLuint flags = 0;
|
||||||
|
|
||||||
|
|
||||||
|
flags |= (driCompareGLXAPIVersion( 20030317 ) >= 0)
|
||||||
|
? VBLANK_FLAG_INTERVAL : 0;
|
||||||
|
flags |= (getenv("LIBGL_SYNC_REFRESH") != NULL)
|
||||||
|
? VBLANK_FLAG_SYNC : 0;
|
||||||
|
flags |= (getenv("LIBGL_THROTTLE_REFRESH") != NULL)
|
||||||
|
? VBLANK_FLAG_THROTTLE : 0;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* Wrapper to call \c drmWaitVBlank. The main purpose of this function is to
|
||||||
|
* wrap the error message logging. The error message should only be logged
|
||||||
|
* the first time the \c drmWaitVBlank fails. If \c drmWaitVBlank is
|
||||||
|
* successful, \c vbl_seq will be set the sequence value in the reply.
|
||||||
|
*
|
||||||
|
* \param vbl Pointer to drmVBlank packet desribing how to wait.
|
||||||
|
* \param vbl_seq Location to store the current refresh counter.
|
||||||
|
* \param fd File descriptor use to call into the DRM.
|
||||||
|
* \return Zero on success or -1 on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
ret = drmWaitVBlank( fd, vbl );
|
||||||
|
if ( ret != 0 ) {
|
||||||
|
static GLboolean first_time = GL_TRUE;
|
||||||
|
|
||||||
|
if ( first_time ) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: drmWaitVBlank returned %d, IRQs don't seem to be"
|
||||||
|
" working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
|
||||||
|
" and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
|
||||||
|
first_time = GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*vbl_seq = vbl->reply.sequence;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* Waits for the vertical blank for use with glXSwapBuffers.
|
||||||
|
*
|
||||||
|
* \param vbl_seq Vertical blank sequence number (MSC) after the last buffer
|
||||||
|
* swap. Updated after this wait.
|
||||||
|
* \param flags \c VBLANK_FLAG bits that control how long to wait.
|
||||||
|
* \param missed_deadline Set to \c GL_TRUE if the MSC after waiting is later
|
||||||
|
* than the "target" based on \c flags. The idea is that if
|
||||||
|
* \c missed_deadline is set, then the application is not
|
||||||
|
* achieving its desired framerate.
|
||||||
|
* \return Zero on success, -1 on error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
driWaitForVBlank( const __DRIdrawablePrivate *priv, GLuint * vbl_seq,
|
||||||
|
GLuint flags, GLboolean * missed_deadline )
|
||||||
|
{
|
||||||
|
drmVBlank vbl;
|
||||||
|
unsigned original_seq;
|
||||||
|
unsigned deadline;
|
||||||
|
unsigned interval;
|
||||||
|
|
||||||
|
|
||||||
|
*missed_deadline = GL_FALSE;
|
||||||
|
if ( (flags & VBLANK_FLAG_NO_IRQ) != 0 ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* VBLANK_FLAG_SYNC means to wait for at least one vertical blank. If
|
||||||
|
* that flag is not set, do a fake wait for zero vertical blanking
|
||||||
|
* periods so that we can get the current MSC.
|
||||||
|
*
|
||||||
|
* VBLANK_FLAG_INTERVAL and VBLANK_FLAG_THROTTLE mean to wait for at
|
||||||
|
* least one vertical blank since the last wait. Since do_wait modifies
|
||||||
|
* vbl_seq, we have to save the original value of vbl_seq for the
|
||||||
|
* VBLANK_FLAG_INTERVAL / VBLANK_FLAG_THROTTLE calculation later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
original_seq = *vbl_seq;
|
||||||
|
|
||||||
|
vbl.request.sequence = ((flags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
|
||||||
|
vbl.request.type = DRM_VBLANK_RELATIVE;
|
||||||
|
|
||||||
|
if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vbl.request.type = DRM_VBLANK_ABSOLUTE;
|
||||||
|
|
||||||
|
if ( (flags & VBLANK_FLAG_INTERVAL) != 0 ) {
|
||||||
|
#ifndef _SOLO
|
||||||
|
interval = priv->pdraw->swap_interval;
|
||||||
|
#else
|
||||||
|
interval = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if ( (flags & VBLANK_FLAG_THROTTLE) != 0 ) {
|
||||||
|
interval = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interval = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Wait until the next vertical blank. If the interval is zero, then
|
||||||
|
* the deadline is one vertical blank after the previous wait.
|
||||||
|
*/
|
||||||
|
|
||||||
|
vbl.request.sequence = original_seq + interval;
|
||||||
|
if ( *vbl_seq < vbl.request.sequence ) {
|
||||||
|
if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deadline = original_seq + ((interval == 0) ? 1 : interval);
|
||||||
|
*missed_deadline = ( *vbl_seq > deadline );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* -*- mode: c; c-basic-offset: 3 -*- */
|
||||||
|
/*
|
||||||
|
* (c) Copyright IBM Corporation 2002
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ian Romanick <idr@us.ibm.com>
|
||||||
|
*/
|
||||||
|
/* $XFree86:$ */
|
||||||
|
|
||||||
|
#ifndef DRI_VBLANK_H
|
||||||
|
#define DRI_VBLANK_H
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
|
#include "dri_util.h"
|
||||||
|
|
||||||
|
#define VBLANK_FLAG_INTERVAL (1U << 0) /* Respect the swap_interval setting
|
||||||
|
*/
|
||||||
|
#define VBLANK_FLAG_THROTTLE (1U << 1) /* Wait 1 refresh since last call.
|
||||||
|
*/
|
||||||
|
#define VBLANK_FLAG_SYNC (1U << 2) /* Sync to the next refresh.
|
||||||
|
*/
|
||||||
|
#define VBLANK_FLAG_NO_IRQ (1U << 7) /* DRM has no IRQ to wait on.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count );
|
||||||
|
extern int driWaitForMSC32( __DRIdrawablePrivate *priv,
|
||||||
|
int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
|
||||||
|
extern GLuint driGetDefaultVBlankFlags( void );
|
||||||
|
extern int driWaitForVBlank( const __DRIdrawablePrivate *priv,
|
||||||
|
GLuint * vbl_seq, GLuint flags, GLboolean * missed_deadline );
|
||||||
|
|
||||||
|
#undef usleep
|
||||||
|
#include <unistd.h> /* for usleep() */
|
||||||
|
|
||||||
|
#define DO_USLEEP(nr) \
|
||||||
|
do { \
|
||||||
|
if (0) fprintf(stderr, "%s: usleep for %u\n", __FUNCTION__, nr ); \
|
||||||
|
if (1) usleep( nr ); \
|
||||||
|
sched_yield(); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
#endif /* DRI_VBLANK_H */
|
Loading…
Reference in New Issue