Compare commits

...

53 Commits

Author SHA1 Message Date
Keith Whitwell
b3b325e560 get 3d textures working again 2006-02-23 11:47:36 +00:00
Keith Whitwell
382ce985ac Fix cubemap layout 2006-02-22 19:54:32 +00:00
Keith Whitwell
54b7eca7a0 Append an MI_FLUSH to each batchbuffer for synchronization. Not really
ideal from a performance viewpoint and there are mechanisms to avoid this
in future.
2006-02-22 19:26:37 +00:00
Keith Whitwell
f74e06bf11 restore swapbuffers throttling 2006-02-22 17:18:19 +00:00
Keith Whitwell
9c02649d18 Introduce fixup/relocation lists for dma buffers. 2006-02-22 15:16:01 +00:00
Keith Whitwell
2c34704e41 tweaks 2006-02-13 00:41:33 +00:00
Keith Whitwell
85d0041ff0 rename texdown to reflect behaviour changes 2006-02-13 00:40:33 +00:00
Keith Whitwell
67ff8b354e bump driver date, etc 2006-02-13 00:39:20 +00:00
Keith Whitwell
08e7957571 Fix inverted image in copytexsubimage by tickling the hardware to
do the inversion in the blitter.
2006-02-13 00:38:46 +00:00
Keith Whitwell
9c1f7089d8 Some functions had been indented by one space?! 2006-02-11 04:28:13 +00:00
Keith Whitwell
5381ac5f11 move blit functions to new file 2006-02-11 02:54:09 +00:00
Keith Whitwell
a6f78d4eee Use aligned malloc for backing store, if necessary. 2006-02-10 00:01:45 +00:00
Keith Whitwell
ae695e3566 Remove 2nd copy of do_memcpy 2006-02-09 23:09:47 +00:00
Keith Whitwell
c82c3335e1 fix refcounting and other issues 2006-02-09 23:06:23 +00:00
Keith Whitwell
f8246f504b Add basic timing for memcpys 2006-02-09 23:04:44 +00:00
Keith Whitwell
499458bcdb Add INVARIENT to the active state list 2006-02-09 23:01:34 +00:00
Keith Whitwell
37a53fd6a0 Make various changes to get a number out of texdown that better
represents realworld usage.  In particular, avoid situations where
the client texture image and the mesa copy (if there is one) are both
resident in L2 cache.
2006-02-09 22:52:20 +00:00
Keith Whitwell
5ec38fb2ea Turn DBG output on/off with INTEL_DEBUG=bufs 2006-02-09 22:21:20 +00:00
Keith Whitwell
11c0215bf8 Switch between memcpy implementations according to src/dest alignment. 2006-02-01 18:42:16 +00:00
Keith Whitwell
6a13b6c346 Debug off 2006-02-01 18:30:16 +00:00
Keith Whitwell
a103097ee5 Quieten depend 2006-02-01 18:29:56 +00:00
Keith Whitwell
7efad0d84c Just build the i915 on this branch 2006-02-01 18:29:25 +00:00
Keith Whitwell
42c88cd072 subtexrate test on this branch too 2006-02-01 18:14:09 +00:00
Keith Whitwell
2541c54e79 gearbox demo on this branch too 2006-02-01 18:13:23 +00:00
Keith Whitwell
33529e3d8e Bump driver date 2006-02-01 18:01:04 +00:00
Keith Whitwell
84c1b82081 Disable check_copytex_fragment_ops - it doesn't really apply. 2006-02-01 16:40:23 +00:00
Keith Whitwell
a97a1439ae Get batchbuffers working natively again. This code still
relies over-heavily on the DRI lock to protect offsets in the
command stream from changing before being queued on the ring,
and should be viewed as being a pretty temporary mechanism
before a more robust alternative is implemented, most likely
based on a batchbuffer relocation list that will be used
to patch prebuilt batchbuffers after validation takes place.
2006-02-01 15:54:42 +00:00
Keith Whitwell
2fd2910010 Remove the last of the old AllocateAgp mechanism.
Move the batchbuffer code to being effectively a ring of
bufmgr buffers.
2006-02-01 15:51:31 +00:00
Keith Whitwell
fbbda155e0 Add code to map/unmap all texture images for the software rasterizer.
Add the color and depth buffers to the validation list to ensure they
are fenced correctly by hardware rasterization.
2006-02-01 15:50:14 +00:00
Keith Whitwell
a49c3c0fae Ensure that color buffers and textures are mapped (bmBufferMap) before
software rasterizer fallbacks.  This has two functions, firstly to
ensure that the Data pointers point to something and secondly to
ensure than any pending fences on those buffers are discharged before
allowing the software rasterizer to read/write the data.

This needs to be integrated with Brian's validate code.
2006-02-01 15:48:52 +00:00
Keith Whitwell
baf5998d59 file gearbox.c was added on branch texman_0_1_branch on 2006-02-01 18:13:23 +0000 2006-01-30 15:35:35 +00:00
Keith Whitwell
4c5acef241 Get hardware-accelerated CopyTexSubImage working well enough to run
Brian's gearbox demo.
2006-01-28 23:28:14 +00:00
Keith Whitwell
9839e272cf Allow ValidateBuffers to allocate memory for buffers which haven't yet
got it by other methods.  Typically this is buffers being written to by
hardware excluding the fixed front/back/depth buffers which are have
pre-allocated memory.

At some point will want to pass BM_READ/BM_WRITE flags to catch the
couple of cases where buffers are treated differently in each case.
2006-01-28 23:27:39 +00:00
Keith Whitwell
b57e79ff14 remove debug 2006-01-28 17:52:50 +00:00
Keith Whitwell
43824acb4e Build fixes 2006-01-28 17:52:05 +00:00
Keith Whitwell
d8f509e749 Use the x86 __memcpy to avoid performance clif for uploads where the
source data is worse than 64-byte aligned.
2006-01-28 17:50:59 +00:00
Keith Whitwell
eb91c93c2e file subtexrate.c was added on branch texman_0_1_branch on 2006-02-01 18:14:09 +0000 2006-01-27 15:44:40 +00:00
Keith Whitwell
79de983b6f initial copytexsubimage code, untested 2006-01-27 11:58:00 +00:00
Brian Paul
fdb3acf016 added _swrast_eject_texture_images() 2006-01-27 03:42:56 +00:00
Keith Whitwell
2807d1f58a Get readbuffer correctly. 2006-01-26 18:30:34 +00:00
Keith Whitwell
93f913926e - Remove (most of) old agp client memory hack.
- Implement an accelerated version of glCopyPixels using the blitter.
2006-01-26 17:21:38 +00:00
Keith Whitwell
33ca04f379 Expand the buffer manager to include a notion of multiple pools within
a memory space.  Allow some pools to be excluded from the upload/evict
processing, meaning that any buffers within those pools are effectively
fixed.  Add a mechanism to create buffers in those pools.

This allows the legacy fixed front/depth/back buffers to be represented
in this scheme and will allow other future pinned buffers to be allocated
from fixed pools in such a way that they cannot fragment the rest of
the texture memory.
2006-01-26 14:50:02 +00:00
Brian Paul
398cb30c72 Added _swrast_validate_texture_images() to make sure all textures have
data resident for software rasterization.
Relies on new swrast driver function: ValidateTextureImage()
2006-01-26 04:05:53 +00:00
Keith Whitwell
f67bb30314 Fix confusion over pitch. demos/texobj renders correctly. 2006-01-25 17:16:46 +00:00
Keith Whitwell
4578d7b9f0 Offset returns weren't being returned. 2006-01-25 16:57:36 +00:00
Keith Whitwell
dcdfc154c3 Remove silly debug. 2006-01-25 16:46:10 +00:00
Keith Whitwell
696ba32779 Another texture manager checkpoint:
- Add code to validate textures before use.
- Simplify vertex paths for now.
- Make vertex paths validate textures.  This is done pretty
  with some pretty heavy-handed use of the dri lock - fixing this is
  a priority.
- Add lots of debug statements

demos/texobj renders, but textures are incorrect.
2006-01-25 15:40:50 +00:00
Keith Whitwell
dcfe55539f Remove dead code. Gears runs. 2006-01-24 18:55:52 +00:00
Keith Whitwell
ff84b1f1b2 Checkpoint of texture manager rework for i915.
Compiles but won't do any more than that.
2006-01-24 18:35:53 +00:00
Keith Whitwell
3bca9c47f4 Add another layer on top of the simple 2d regions in intel_regions.[ch]
which keeps track of a whole, well-defined mipmap tree.  These are a
fixed layout on intel hardware and managing them is complicated in the
face of GL's TexImage function calls where data can arrive in any order,
making it difficult to guess a layout ahead of time.

Wrapping mipmap trees up in a struct and programming interface like this
reduces the burden elsewhere.
2006-01-24 16:38:43 +00:00
Keith Whitwell
d4d7fdb43b layer 2d region semantics and blits on top of bufmgr buffers 2006-01-23 12:53:11 +00:00
Keith Whitwell
d65dab5777 import via texture semantics 2006-01-23 12:52:28 +00:00
Keith Whitwell
638ca019ef Add a faked-out implementation of the buffer manager that uses the same
techniques as the old dri memory manager behind the new interface.  Will
use this to port the i915 driver to this interface to hopefully get
some easy insights from using the interface.
2006-01-16 15:30:45 +00:00
68 changed files with 8272 additions and 4957 deletions

View File

@@ -9,7 +9,7 @@ CONFIG_NAME = linux-dri
CC = gcc
CXX = g++
MKDEP = /usr/X11R6/bin/makedepend
#MKDEP = /usr/X11R6/bin/makedepend
#MKDEP = gcc -M
#MKDEP_OPTIONS = -MF depend
@@ -63,5 +63,7 @@ WINDOW_SYSTEM=dri
# gamma are missing because they have not been converted to use the new
# interface.
DRI_DIRS = i810 i830 i915 mach64 mga r128 r200 r300 radeon s3v \
DRI_DIRS = i810 i915 mach64 mga r128 r200 r300 radeon s3v \
savage sis tdfx trident unichrome ffb
DRI_DIRS = i915

View File

@@ -25,6 +25,7 @@ PROGS = \
fplight \
gamma \
gears \
gearbox \
geartrain \
glinfo \
gloss \
@@ -51,7 +52,7 @@ PROGS = \
terrain \
tessdemo \
texcyl \
texdown \
texdown-pool \
texenv \
texobj \
trispd \
@@ -73,9 +74,8 @@ PROGS = \
##### TARGETS #####
default: $(PROGS)
default: readtex.o $(PROGS)
$(PROGS): readtex.o
readtex.c: $(TOP)/progs/util/readtex.c
cp $< .

486
progs/demos/gearbox.c Normal file
View File

@@ -0,0 +1,486 @@
/*
* Use glCopyTexSubImage2D to draw animated gears on the sides of a box.
*
* Brian Paul
* 27 January 2006
*/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glut.h>
#ifndef M_PI
#define M_PI 3.14159265
#endif
static GLint WinWidth = 800, WinHeight = 500;
static GLint TexWidth, TexHeight;
static GLuint TexObj = 1;
static GLenum IntFormat = GL_RGBA;
static GLboolean WireFrame = GL_FALSE;
static GLint T0 = 0;
static GLint Frames = 0;
static GLint Win = 0;
static GLfloat ViewRotX = 20.0, ViewRotY = 30.0, ViewRotZ = 0.0;
static GLint Gear1, Gear2, Gear3;
static GLfloat GearRot = 0.0;
static GLfloat CubeRot = 0.0;
/**
Draw a gear wheel. You'll probably want to call this function when
building a display list since we do a lot of trig here.
Input: inner_radius - radius of hole at center
outer_radius - radius at center of teeth
width - width of gear
teeth - number of teeth
tooth_depth - depth of tooth
**/
static void
gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
GLint teeth, GLfloat tooth_depth)
{
GLint i;
GLfloat r0, r1, r2;
GLfloat angle, da;
GLfloat u, v, len;
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * M_PI / teeth / 4.0;
glShadeModel(GL_FLAT);
glNormal3f(0.0, 0.0, 1.0);
/* draw front face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
if (i < teeth) {
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
}
glEnd();
/* draw front sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
glEnd();
glNormal3f(0.0, 0.0, -1.0);
/* draw back face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
if (i < teeth) {
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
}
}
glEnd();
/* draw back sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
}
glEnd();
/* draw outward faces of teeth */
glBegin(GL_QUAD_STRIP);
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
u = r2 * cos(angle + da) - r1 * cos(angle);
v = r2 * sin(angle + da) - r1 * sin(angle);
len = sqrt(u * u + v * v);
u /= len;
v /= len;
glNormal3f(v, -u, 0.0);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
glNormal3f(v, -u, 0.0);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
}
glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
glEnd();
glShadeModel(GL_SMOOTH);
/* draw inside radius cylinder */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glNormal3f(-cos(angle), -sin(angle), 0.0);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
}
glEnd();
}
static void
cleanup(void)
{
glDeleteTextures(1, &TexObj);
glDeleteLists(Gear1, 1);
glDeleteLists(Gear2, 1);
glDeleteLists(Gear3, 1);
glutDestroyWindow(Win);
}
static void
DrawGears(void)
{
if (WireFrame) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
glPushMatrix();
glRotatef(20/*ViewRotX*/, 1.0, 0.0, 0.0);
glRotatef(ViewRotY, 0.0, 1.0, 0.0);
glRotatef(ViewRotZ, 0.0, 0.0, 1.0);
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(GearRot, 0.0, 0.0, 1.0);
glCallList(Gear1);
glPopMatrix();
glPushMatrix();
glTranslatef(3.1, -2.0, 0.0);
glRotatef(-2.0 * GearRot - 9.0, 0.0, 0.0, 1.0);
glCallList(Gear2);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.1, 4.2, 0.0);
glRotatef(-2.0 * GearRot - 25.0, 0.0, 0.0, 1.0);
glCallList(Gear3);
glPopMatrix();
glPopMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
static void
DrawCube(void)
{
static const GLfloat texcoords[4][2] = {
{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
};
static const GLfloat vertices[4][2] = {
{ -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
};
static const GLfloat xforms[6][4] = {
{ 0, 0, 1, 0 },
{ 90, 0, 1, 0 },
{ 180, 0, 1, 0 },
{ 270, 0, 1, 0 },
{ 90, 1, 0, 0 },
{ -90, 1, 0, 0 }
};
static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
GLint i, j;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glRotatef(ViewRotX, 1.0, 0.0, 0.0);
glRotatef(15, 1, 0, 0);
glRotatef(CubeRot, 0, 1, 0);
glScalef(4, 4, 4);
for (i = 0; i < 6; i++) {
glPushMatrix();
glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
glTranslatef(0, 0, 1.1);
glBegin(GL_POLYGON);
glNormal3f(0, 0, 1);
for (j = 0; j < 4; j++) {
glTexCoord2fv(texcoords[j]);
glVertex2fv(vertices[j]);
}
glEnd();
glPopMatrix();
}
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
static void
draw(void)
{
float ar;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -40.0);
glDisable(GL_SCISSOR_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
/* draw gears */
glViewport(0, 0, TexWidth, TexHeight);
glScissor(0, 0, TexWidth, TexHeight);
glClearColor(0.5, 0.5, 0.8, 0.0);
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 60.0);
glMatrixMode(GL_MODELVIEW);
DrawGears();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
/* draw textured cube */
glViewport(TexWidth, 0, WinWidth - TexWidth, WinHeight);
glScissor(TexWidth, 0, WinWidth - TexWidth, WinHeight);
glClearColor(0.5, 0.5, 0.8, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
ar = (float) (WinWidth - TexWidth) / WinHeight;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
glMatrixMode(GL_MODELVIEW);
DrawCube();
/* finish up */
glutSwapBuffers();
Frames++;
{
GLint t = glutGet(GLUT_ELAPSED_TIME);
if (t - T0 >= 5000) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
T0 = t;
Frames = 0;
}
}
}
static void
idle(void)
{
static double t0 = -1.;
double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
if (t0 < 0.0)
t0 = t;
dt = t - t0;
t0 = t;
GearRot += 70.0 * dt; /* 70 degrees per second */
GearRot = fmod(GearRot, 360.0); /* prevents eventual overflow */
CubeRot += 15.0 * dt;
glutPostRedisplay();
}
/* change view angle, exit upon ESC */
static void
key(unsigned char k, int x, int y)
{
(void) x;
(void) y;
switch (k) {
case 'w':
WireFrame = !WireFrame;
break;
case 'z':
ViewRotZ += 5.0;
break;
case 'Z':
ViewRotZ -= 5.0;
break;
case 27: /* Escape */
cleanup();
exit(0);
break;
default:
return;
}
glutPostRedisplay();
}
/* change view angle */
static void
special(int k, int x, int y)
{
(void) x;
(void) y;
switch (k) {
case GLUT_KEY_UP:
ViewRotX += 5.0;
break;
case GLUT_KEY_DOWN:
ViewRotX -= 5.0;
break;
case GLUT_KEY_LEFT:
ViewRotY += 5.0;
break;
case GLUT_KEY_RIGHT:
ViewRotY -= 5.0;
break;
default:
return;
}
glutPostRedisplay();
}
/* new window size or exposure */
static void
reshape(int width, int height)
{
WinWidth = width;
WinHeight = height;
}
static void
init(int argc, char *argv[])
{
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
GLint i;
glLightfv(GL_LIGHT0, GL_POSITION, pos);
#if 0
glEnable(GL_CULL_FACE);
#endif
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
/* make the gears */
Gear1 = glGenLists(1);
glNewList(Gear1, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
gear(1.0, 4.0, 1.0, 20, 0.7);
glEndList();
Gear2 = glGenLists(1);
glNewList(Gear2, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gear(0.5, 2.0, 2.0, 10, 0.7);
glEndList();
Gear3 = glGenLists(1);
glNewList(Gear3, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
gear(1.3, 2.0, 0.5, 10, 0.7);
glEndList();
glEnable(GL_NORMALIZE);
/* xxx make size dynamic */
TexWidth = 256;
TexHeight = 256;
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
for ( i=1; i<argc; i++ ) {
if (strcmp(argv[i], "-info")==0) {
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
}
}
}
static void
visible(int vis)
{
if (vis == GLUT_VISIBLE)
glutIdleFunc(idle);
else
glutIdleFunc(NULL);
}
int
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(WinWidth, WinHeight);
Win = glutCreateWindow("gearbox");
init(argc, argv);
glutDisplayFunc(draw);
glutReshapeFunc(reshape);
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutVisibilityFunc(visible);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}

View File

@@ -38,8 +38,8 @@
#include <GL/glut.h>
static GLsizei MaxSize = 1024;
static GLsizei TexWidth = 256, TexHeight = 256, TexBorder = 0;
static GLsizei MaxSize = 2048;
static GLsizei TexWidth = 1024, TexHeight = 1024, TexBorder = 0;
static GLboolean ScaleAndBias = GL_FALSE;
static GLboolean SubImage = GL_FALSE;
static GLdouble DownloadRate = 0.0; /* texels/sec */
@@ -47,6 +47,32 @@ static GLdouble DownloadRate = 0.0; /* texels/sec */
static GLuint Mode = 0;
/* Try and avoid L2 cache effects by cycling through a small number of
* textures.
*
* At the initial size of 1024x1024x4 == 4mbyte, say 8 textures will
* keep us out of most caches at 32mb total.
*
* This turns into a fairly interesting question of what exactly you
* expect to be in cache in normal usage, and what you think should be
* outside. There's no rules for this, no reason to favour one usage
* over another except what the application you care about happens to
* resemble most closely.
*
* - Should the client texture image be in L2 cache? Has it just been
* generated or read from disk?
* - Does the application really use >1 texture, or is it constantly
* updating one image in-place?
*
* Different answers will favour different texture upload mechanisms.
* To upload an image that is purely outside of cache, a DMA-based
* upload will probably win, whereas for small, in-cache textures,
* copying looks good.
*/
#define NR_TEXOBJ 4
static GLuint TexObj[NR_TEXOBJ];
struct FormatRec {
GLenum Format;
GLenum Type;
@@ -116,25 +142,57 @@ TypeStr(GLenum type)
}
}
/* On x86, there is a performance cliff for memcpy to texture memory
* for sources below 64 byte alignment. We do our best with this in
* the driver, but it is better if the images are correctly aligned to
* start with:
*/
#define ALIGN (1<<12)
static unsigned align(unsigned value, unsigned a)
{
return (value + a - 1) & ~(a-1);
}
static int MIN2(int a, int b)
{
return a < b ? a : b;
}
static void
MeasureDownloadRate(void)
{
const int w = TexWidth + 2 * TexBorder;
const int h = TexHeight + 2 * TexBorder;
const int bytes = w * h * BytesPerTexel(Format);
const int image_bytes = align(w * h * BytesPerTexel(Format), ALIGN);
const int bytes = image_bytes * NR_TEXOBJ;
GLubyte *orig_texImage, *orig_getImage;
GLubyte *texImage, *getImage;
GLdouble t0, t1, time;
int count;
int i;
int offset = 0;
GLdouble total = 0; /* ints will tend to overflow */
texImage = (GLubyte *) malloc(bytes);
getImage = (GLubyte *) malloc(bytes);
if (!texImage || !getImage) {
printf("allocating %d bytes for %d %dx%d images\n",
bytes, NR_TEXOBJ, w, h);
orig_texImage = (GLubyte *) malloc(bytes + ALIGN);
orig_getImage = (GLubyte *) malloc(image_bytes + ALIGN);
if (!orig_texImage || !orig_getImage) {
DownloadRate = 0.0;
return;
}
printf("alloc %p %p\n", orig_texImage, orig_getImage);
texImage = (GLubyte *)align((unsigned)orig_texImage, ALIGN);
getImage = (GLubyte *)align((unsigned)orig_getImage, ALIGN);
for (i = 1; !(((unsigned)texImage) & i); i<<=1)
;
printf("texture image alignment: %d bytes (%p)\n", i, texImage);
for (i = 0; i < bytes; i++) {
texImage[i] = i & 0xff;
}
@@ -166,51 +224,80 @@ MeasureDownloadRate(void)
count = 0;
t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
do {
int img = count%NR_TEXOBJ;
GLubyte *img_ptr = texImage + img * image_bytes;
glBindTexture(GL_TEXTURE_2D, TexObj[img]);
if (SubImage && count > 0) {
glTexSubImage2D(GL_TEXTURE_2D, 0, -TexBorder, -TexBorder, w, h,
/* Only update a portion of the image each iteration. This
* is presumably why you'd want to use texsubimage, otherwise
* you may as well just call teximage again.
*
* A bigger question is whether to use a pointer that moves
* with each call, ie does the incoming data come from L2
* cache under normal circumstances, or is it pulled from
* uncached memory?
*
* There's a good argument to say L2 cache, ie you'd expect
* the data to have been recently generated. It's possible
* that it could have come from a file read, which may or may
* not have gone through the cpu.
*/
glTexSubImage2D(GL_TEXTURE_2D, 0,
-TexBorder,
-TexBorder + offset * h/8,
w,
h/8,
FormatTable[Format].Format,
FormatTable[Format].Type, texImage);
FormatTable[Format].Type,
#if 1
texImage /* likely in L2$ */
#else
img_ptr + offset * bytes/8 /* unlikely in L2$ */
#endif
);
offset += 1;
offset %= 8;
total += w * h / 8;
}
else {
glTexImage2D(GL_TEXTURE_2D, 0,
FormatTable[Format].IntFormat, w, h, TexBorder,
FormatTable[Format].Format,
FormatTable[Format].Type, texImage);
FormatTable[Format].Type,
img_ptr);
total += w*h;
}
#if 1
/* Render a texture, but not necessarily the one just uploaded.
*/
/* glBindTexture(GL_TEXTURE_2D, TexObj[(img + NR_TEXOBJ/2)%NR_TEXOBJ]); */
/* draw a tiny polygon to force texture into texram */
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0); glVertex2f(1, 1);
glTexCoord2f(1, 0); glVertex2f(3, 1);
glTexCoord2f(0.5, 1); glVertex2f(2, 3);
glEnd();
/* glFinish(); */
#endif
t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
time = t1 - t0;
count++;
/* printf("total %f count %d\n", total, count); */
} while (time < 3.0);
glDisable(GL_TEXTURE_2D);
printf("w*h=%d count=%d time=%f\n", w*h, count, time);
DownloadRate = w * h * count / time;
printf("total texels=%f time=%f\n", total, time);
DownloadRate = total / time;
#if 0
if (!ScaleAndBias) {
/* verify texture readback */
glGetTexImage(GL_TEXTURE_2D, 0,
FormatTable[Format].Format,
FormatTable[Format].Type, getImage);
for (i = 0; i < w * h; i++) {
if (texImage[i] != getImage[i]) {
printf("[%d] %d != %d\n", i, texImage[i], getImage[i]);
}
}
}
#endif
free(texImage);
free(getImage);
free(orig_texImage);
free(orig_getImage);
{
GLint err = glGetError();

View File

@@ -92,7 +92,7 @@ static void idle( void )
dt = t - t0;
t0 = t;
Angle += 120.0*dt;
glutPostRedisplay();
/* glutPostRedisplay(); */
}

View File

@@ -47,6 +47,7 @@ SOURCES = antialias.c \
sharedtex.c \
stencilwrap.c \
stencil_wrap.c \
subtexrate.c \
tex1d.c \
texfilt.c \
texline.c \

378
progs/tests/subtexrate.c Normal file
View File

@@ -0,0 +1,378 @@
/*
* Measure glTexSubImage and glCopyTexSubImage speed
*
* Brian Paul
* 26 Jan 2006
*/
#define GL_GLEXT_PROTOTYPES
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
static GLint WinWidth = 1024, WinHeight = 512;
static GLint TexWidth = 512, TexHeight = 512;
static GLuint TexObj = 1;
static GLenum IntFormat = GL_RGBA;
static GLenum ReadFormat = GL_BGRA; /* for glReadPixels */
static GLboolean DrawQuad = GL_TRUE;
/**
* draw teapot image, size TexWidth by TexHeight
*/
static void
DrawTestImage(void)
{
GLfloat ar;
glViewport(0, 0, TexWidth, TexHeight);
glScissor(0, 0, TexWidth, TexHeight);
glEnable(GL_SCISSOR_TEST);
glClearColor(0.5, 0.5, 0.5, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ar = (float) TexWidth / TexHeight;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CW);
glPushMatrix();
glRotatef(45, 1, 0, 0);
glRotatef(45, 0, 1, 0);
glutSolidTeapot(2.3);
glPopMatrix();
glFrontFace(GL_CCW);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, WinWidth, WinHeight);
glFinish();
}
/**
* Do glCopyTexSubImage2D call (update texture with framebuffer data)
* If doSubRect is true, do the copy in four pieces instead of all at once.
*/
static void
DoCopyTex(GLboolean doSubRect)
{
if (doSubRect) {
/* copy in four parts */
int w = TexWidth / 2, h = TexHeight / 2;
int x0 = 0, y0 = 0;
int x1 = w, y1 = h;
#if 0
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x0, y0, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x1, y0, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x0, y1, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x1, y1, w, h);
#else
/* scramble */
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x1, y1, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x0, y1, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x1, y0, w, h);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x0, y0, w, h);
#endif
}
else {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
}
}
/**
* Do glTexSubImage2D (update texture w/ user data)
* If doSubRect, do update in four pieces, else all at once.
*/
static void
SubTex(GLboolean doSubRect, const GLubyte *image)
{
if (doSubRect) {
/* four pieces */
int w = TexWidth / 2, h = TexHeight / 2;
int x0 = 0, y0 = 0;
int x1 = w, y1 = h;
glPixelStorei(GL_UNPACK_ROW_LENGTH, TexWidth);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei( GL_PACK_INVERT_MESA, GL_TRUE );
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */
glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, w, h,
ReadFormat, GL_UNSIGNED_BYTE, image);
glPixelStorei( GL_PACK_INVERT_MESA, GL_FALSE );
}
else {
/* all at once */
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexWidth, TexHeight,
ReadFormat, GL_UNSIGNED_BYTE, image);
}
}
/**
* Measure gl[Copy]TexSubImage rate.
* This actually also includes time to render a quad and SwapBuffers.
*/
static void
RunTest(GLboolean copyTex, GLboolean doSubRect)
{
double t0, t1;
int iters = 0;
float copyRate, mbRate;
float rot = 0.0;
int bpp, r, g, b, a;
int w, h;
GLubyte *image = NULL;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a);
bpp = (r + g + b + a) / 8;
if (!copyTex) {
/* read image from frame buffer */
image = (GLubyte *) malloc(TexWidth * TexHeight * bpp);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, TexWidth, TexHeight,
ReadFormat, GL_UNSIGNED_BYTE, image);
}
glEnable(GL_TEXTURE_2D);
glViewport(WinWidth / 2, 0, WinWidth / 2, WinHeight);
t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
if (!DrawQuad)
glDrawBuffer(GL_FRONT);
do {
if (copyTex)
/* Framebuffer -> Texture */
DoCopyTex(doSubRect);
else {
/* Main Mem -> Texture */
SubTex(doSubRect, image);
}
/* draw textured quad */
if (DrawQuad) {
glPushMatrix();
glRotatef(rot, 0, 0, 1);
glTranslatef(1, 0, 0);
glBegin(GL_POLYGON);
glTexCoord2f(0, 0); glVertex2f(-1, -1);
glTexCoord2f(1, 0); glVertex2f( 1, -1);
glTexCoord2f(1, 1); glVertex2f( 1, 1);
glTexCoord2f(0, 1); glVertex2f(-1, 1);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
else {
/* Draw something tiny to ensure that the texture is really
* uploaded:
*/
glPushMatrix();
glRotatef(rot, 0, 0, 1);
glTranslatef(1, 0, 0);
glBegin(GL_POLYGON);
glTexCoord2f(0, 0); glVertex2f(-.01, -.01);
glTexCoord2f(.01, 0); glVertex2f( .01, -.01);
glTexCoord2f(.01, .01); glVertex2f( .01, .01);
glTexCoord2f(0, .01); glVertex2f(-.01, .01);
glEnd();
glPopMatrix();
glFlush();
}
iters++;
rot += 2.0;
t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
} while (t1 - t0 < 2.0);
/* Make sure everything is done before taking the final timing:
*/
glFinish();
t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
glDisable(GL_TEXTURE_2D);
if (image)
free(image);
if (doSubRect) {
w = TexWidth / 2;
h = TexHeight / 2;
iters *= 4;
}
else {
w = TexWidth;
h = TexHeight;
}
copyRate = iters / (t1 - t0);
mbRate = w * h * bpp * copyRate / (1024 * 1024);
if (copyTex)
printf("glCopyTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
else
printf("glTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
printf(" %d calls in %.2f = %.2f calls/sec, %.2f MB/s\n",
iters, t1-t0, copyRate, mbRate);
}
static void
Draw(void)
{
glClearColor(0.2, 0.2, 0.8, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawTestImage();
if (!DrawQuad) {
glutSwapBuffers();
}
RunTest(GL_FALSE, GL_FALSE);
RunTest(GL_FALSE, GL_TRUE);
RunTest(GL_TRUE, GL_FALSE);
RunTest(GL_TRUE, GL_TRUE);
glutSwapBuffers();
/* printf("exiting\n"); */
/* exit(0); */
}
static void
Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -15.0);
}
static void
Key(unsigned char key, int x, int y)
{
(void) x;
(void) y;
switch (key) {
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void
SpecialKey(int key, int x, int y)
{
(void) x;
(void) y;
switch (key) {
case GLUT_KEY_UP:
break;
case GLUT_KEY_DOWN:
break;
case GLUT_KEY_LEFT:
break;
case GLUT_KEY_RIGHT:
break;
}
glutPostRedisplay();
}
static void
Init(void)
{
/* create initial, empty teximage */
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
static void
ParseArgs(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-nodraw") == 0)
DrawQuad = GL_FALSE;
}
}
int
main(int argc, char *argv[])
{
GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH;
glutInit(&argc, argv);
ParseArgs(argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(WinWidth, WinHeight);
glutInitDisplayMode(mode);
glutCreateWindow(argv[0]);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(SpecialKey);
glutDisplayFunc(Draw);
printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
Init();
glutMainLoop();
return 0;
}

View File

@@ -89,7 +89,7 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME)
depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \
> /dev/null
>& /dev/null
# Emacs tags

View File

@@ -5,33 +5,50 @@ include $(TOP)/configs/current
LIBNAME = i915_dri.so
DRIVER_SOURCES = \
bufmgr_fake.c \
intel_regions.c \
intel_batchbuffer.c \
intel_mipmap_tree.c \
i915_tex_layout.c \
intel_tex_image.c \
intel_tex_subimage.c \
intel_tex_copy.c \
intel_tex_validate.c \
intel_tex_format.c \
intel_tex.c \
intel_pixel.c \
intel_pixel_copy.c \
intel_pixel_read.c \
intel_pixel_draw.c \
intel_buffers.c \
intel_blit.c \
i915_tex.c \
i915_texstate.c \
i915_context.c \
i915_debug.c \
i915_fragprog.c \
i915_metaops.c \
i915_program.c \
i915_state.c \
i915_tex.c \
i915_texprog.c \
i915_texstate.c \
i915_vtbl.c \
intel_context.c \
intel_ioctl.c \
intel_screen.c \
intel_span.c \
intel_state.c \
intel_tris.c
DISABLED = \
intel_render.c \
i830_context.c \
i830_metaops.c \
i830_state.c \
i830_texblend.c \
i830_tex.c \
i830_texstate.c \
i830_vtbl.c \
intel_batchbuffer.c \
intel_context.c \
intel_ioctl.c \
intel_pixel.c \
intel_render.c \
intel_screen.c \
intel_span.c \
intel_state.c \
intel_tex.c \
intel_tris.c
i830_vtbl.c
C_SOURCES = \
$(COMMON_SOURCES) \

View File

@@ -0,0 +1,181 @@
#ifndef BUFMGR_H
#define BUFMGR_H
#include "intel_context.h"
/* Note that this is destined to be external to Mesa, so don't use GL
* types like GLuint, etc.
*/
/* The buffer manager context. Opaque.
*/
struct bufmgr;
#define BM_LIST_MAX 32
/* List of buffers to validate. Probably better managed by the client:
*/
struct bm_buffer_list {
struct {
unsigned buffer;
unsigned *offset_return;
unsigned *memtype_return;
} elem[BM_LIST_MAX];
unsigned nr;
};
struct bufmgr *bm_fake_intel_Attach( struct intel_context *intel );
/* struct bufmgr *bmCreate( ... ); */
/* struct bufmgr *bmAttach( ... ); */
/* Define an address space. Doesn't really do anything, but the
* information could be used to validate the bmInitPool() requests.
*/
void bmInitMemType( struct bufmgr *,
unsigned mem_type,
unsigned long size );
/* Create a pool of a given memory type, from a certain offset and a
* certain size.
*
* Also passed in is a virtual pointer to the start of the pool. This
* is useful in the faked-out version in i915 so that MapBuffer can
* return a pointer to a buffer residing in AGP space.
*
* Flags passed into a pool are inherited by all buffers allocated in
* that pool. So pools representing the static front,back,depth
* buffer allocations should have MEM_AGP|NO_UPLOAD|NO_EVICT|NO_MOVE to match
* the behaviour of the legacy allocations.
*
* Returns -1 for failure, pool number for success.
*/
int bmInitPool( struct bufmgr *,
unsigned long low_offset,
void *low_virtual,
unsigned long size,
unsigned flags);
/* Flags for validate and other calls. If both NO_UPLOAD and NO_EVICT
* are specified, ValidateBuffers is essentially a query.
*/
#define BM_MEM_LOCAL 0x1
#define BM_MEM_AGP 0x2
#define BM_MEM_VRAM 0x4 /* not yet used */
#define BM_WRITE 0x8 /* not yet used */
#define BM_READ 0x10 /* not yet used */
#define BM_NO_UPLOAD 0x20
#define BM_NO_EVICT 0x40
#define BM_NO_MOVE 0x80 /* not yet used */
#define BM_NO_ALLOC 0x100 /* legacy "fixed" buffers only */
#define BM_CLIENT 0x200 /* for map - pointer will be accessed
* without dri lock */
#define BM_MEM_MASK (BM_MEM_LOCAL|BM_MEM_AGP|BM_MEM_VRAM)
/* Stick closely to ARB_vbo semantics - they're well defined and
* understood, and drivers can just pass the calls through without too
* much thunking.
*/
void bmGenBuffers(struct bufmgr *, unsigned n, unsigned *buffers);
void bmDeleteBuffers(struct bufmgr *, unsigned n, unsigned *buffers);
/* Hook to inform faked buffer manager about fixed-position
* front,depth,back buffers. These may move to a fully memory-managed
* scheme, or they may continue to be managed as is.
*/
unsigned bmBufferStatic(struct bufmgr *,
unsigned buffer,
unsigned size,
unsigned pool);
/* The driver has more intimate knowledge of the hardare than a GL
* client would, so flags here is more proscriptive than the usage
* values in the ARB_vbo interface:
*/
void bmBufferData(struct bufmgr *,
unsigned buffer,
unsigned size,
const void *data,
unsigned flags );
void bmBufferSubData(struct bufmgr *,
unsigned buffer,
unsigned offset,
unsigned size,
const void *data );
void *bmMapBuffer( struct bufmgr *,
unsigned buffer,
unsigned access );
void bmUnmapBuffer( struct bufmgr *,
unsigned buffer );
/* To be called prior to emitting commands to hardware which reference
* these buffers.
*
* NewBufferList() and AddBuffer() build up a list of buffers to be
* validated. The buffer list provides information on where the
* buffers should be placed and whether their contents need to be
* preserved on copying. The offset data elements are return values
* from this function telling the driver exactly where the buffers are
* currently located.
*
* ValidateBufferList() performs the actual validation and returns the
* buffer pools and offsets within the pools.
*
* FenceBufferList() must be called to set fences and other
* housekeeping before unlocking after a successful call to
* ValidateBufferList(). The buffer manager knows how to emit and test
* fences directly through the drm and without callbacks to the
* driver.
*/
struct bm_buffer_list *bmNewBufferList( void );
void bmAddBuffer( struct bm_buffer_list *list,
unsigned buffer,
unsigned flags,
unsigned *pool_return,
unsigned *offset_return );
int bmValidateBufferList( struct bufmgr *,
struct bm_buffer_list *,
unsigned flags );
unsigned bmFenceBufferList( struct bufmgr *,
struct bm_buffer_list * );
void bmFreeBufferList( struct bm_buffer_list * );
/* This functionality is used by the buffer manager, not really sure
* if we need to be exposing it in this way, probably libdrm will
* offer equivalent calls.
*
* For now they can stay, but will likely change/move before final:
*/
unsigned bmSetFence( struct bufmgr * );
int bmTestFence( struct bufmgr *, unsigned fence );
void bmFinishFence( struct bufmgr *, unsigned fence );
void bmFlushReadCaches( struct bufmgr *bm );
void bmFlushDrawCache( struct bufmgr *bm );
void bm_fake_NotifyContendedLockTake( struct bufmgr * );
extern int INTEL_DEBUG;
#define DEBUG_BUFMGR 0x2000
#define DBG(...) do { if (INTEL_DEBUG & DEBUG_BUFMGR) _mesa_printf(__VA_ARGS__); } while(0)
#endif

View File

@@ -0,0 +1,858 @@
/* Fake version of the buffer manager so that we can prototype the
* changes in a driver fairly quickly. Basically wraps the old style
* memory management in the new programming interface.
*
* This version imports code from the via memory manager to closer
* approximate the behaviour of a true memory manager. In particular,
* in this version we do not expect to lose texture memory contents on
* context switches.
*/
#include "bufmgr.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "hash.h"
#include "simple_list.h"
#include "mm.h"
#include "imports.h"
struct _mesa_HashTable;
static int delayed_free( struct bufmgr *bm );
#define BM_POOL_MAX 8
/* Wrapper around mm.c's mem_block, which understands that you must
* wait for fences to expire before memory can be freed. This is
* specific to our use of memcpy for uploads - an upload that was
* processed through the command queue wouldn't need to care about
* fences.
*/
struct block {
struct block *next, *prev;
int mem_type;
struct pool *pool; /* BM_MEM_AGP */
struct mem_block *mem; /* BM_MEM_AGP */
unsigned fence; /* BM_MEM_AGP, Split to read_fence, write_fence */
void *virtual;
struct buffer *buf;
};
struct buffer {
unsigned id; /* debug only */
unsigned size;
unsigned alignment;
unsigned mapped;
unsigned flags;
struct block *block;
};
struct pool {
unsigned flags;
struct mem_block *heap;
void *virtual;
struct block lru;
struct block freed;
};
struct bufmgr {
struct intel_context *intel;
struct pool pool[BM_POOL_MAX];
unsigned nr_pools;
struct _mesa_HashTable *hash;
unsigned buf_nr; /* for generating ids */
};
static struct block *alloc_from_pool( struct bufmgr *bm,
unsigned pool_nr,
unsigned size,
unsigned align )
{
struct pool *pool = &bm->pool[pool_nr];
struct block *block = (struct block *)calloc(sizeof *block, 1);
if (!block)
return NULL;
DBG("alloc_from_pool %d sz 0x%x\n", pool_nr, size);
assert(align >= 7);
block->mem = mmAllocMem(pool->heap, size, align, 0);
if (!block->mem) {
DBG("\t- failed\n");
free(block);
return NULL;
}
make_empty_list(block);
block->pool = pool;
block->mem_type = pool->flags & BM_MEM_MASK;
block->virtual = pool->virtual + block->mem->ofs;
DBG("\t- offset 0x%x\n", block->mem->ofs);
return block;
}
static struct block *alloc_local( unsigned size )
{
struct block *block = (struct block *)calloc(sizeof *block, 1);
if (!block)
return NULL;
DBG("alloc_local 0x%x\n", size);
block->mem_type = BM_MEM_LOCAL;
block->virtual = ALIGN_MALLOC(size, 1<<7);
if (!block->virtual) {
free(block);
return NULL;
}
return block;
}
static struct block *alloc_block( struct bufmgr *bm,
unsigned size,
unsigned align,
int flags )
{
GLuint i;
if (!(flags & BM_CLIENT)) {
for (i = 0; i < bm->nr_pools; i++) {
struct block *block;
if (bm->pool[i].flags & BM_NO_ALLOC)
continue;
if ((bm->pool[i].flags & flags & BM_MEM_MASK) == 0)
continue;
block = alloc_from_pool(bm, i, size, align);
if (block)
return block;
}
}
if (flags & BM_MEM_LOCAL)
return alloc_local(size);
return NULL;
}
static int bmAllocMem( struct bufmgr *bm,
struct buffer *buf,
GLuint flags )
{
delayed_free(bm);
buf->block = alloc_block(bm,
buf->size,
buf->alignment,
buf->flags | flags);
if (buf->block)
buf->block->buf = buf;
else
_mesa_printf("bmAllocMem failed memflags %x\n", buf->flags & BM_MEM_MASK);
/* Sleep here or fail???
*/
/* assert(buf->block); */
return buf->block != NULL;
}
/* Release the card storage associated with buf:
*/
static void free_block( struct bufmgr *bm, struct block *block )
{
DBG("free block %p\n", block);
if (!block)
return;
DBG("free block (mem: %d, sz %d) from buf %d\n",
block->mem_type,
block->buf->size,
block->buf->id);
switch (block->mem_type) {
case BM_MEM_AGP:
case BM_MEM_VRAM:
remove_from_list(block);
DBG(" - offset %x\n", block->mem->ofs);
if (bmTestFence(bm, block->fence)) {
DBG(" - free immediately\n");
mmFreeMem(block->mem);
free(block);
}
else {
DBG(" - place on delayed_free list\n");
block->buf = NULL;
insert_at_tail(&block->pool->freed, block);
}
break;
case BM_MEM_LOCAL:
DBG(" - free local memory\n");
ALIGN_FREE(block->virtual);
free(block);
break;
default:
DBG(" - unknown memory type\n");
free(block);
break;
}
}
static int delayed_free( struct bufmgr *bm )
{
struct block *block, *tmp;
int ret = 0;
int i;
for (i = 0; i < bm->nr_pools; i++) {
foreach_s(block, tmp, &bm->pool[i].freed ) {
if (bmTestFence(bm, block->fence)) {
ret += block->mem->size;
remove_from_list(block);
mmFreeMem(block->mem);
free(block);
}
}
}
DBG("%s: %d\n", __FUNCTION__, ret);
return ret;
}
static int move_buffers( struct bufmgr *bm,
struct buffer *buffers[],
int nr,
int flags )
{
struct block *newMem[BM_LIST_MAX];
GLint i;
GLuint nr_uploads = 0;
DBG("%s\n", __FUNCTION__);
memset(newMem, 0, sizeof(newMem));
/* First do all the allocations (or fail):
*/
for (i = 0; i < nr; i++) {
if (!buffers[i]->block) {
if (flags & BM_NO_ALLOC)
goto cleanup;
newMem[i] = alloc_block(bm,
buffers[i]->size,
buffers[i]->alignment,
flags & BM_MEM_MASK);
if (!newMem[i])
goto cleanup;
}
else if (!(buffers[i]->block->mem_type & flags)) {
if (flags & BM_NO_UPLOAD)
goto cleanup;
/* Known issue: this assert will get hit on texture swapping.
* There's not much to do about that at this stage - it's a
* todo item.
*/
assert(!buffers[i]->mapped);
DBG("try to move buffer %d size 0x%x to pools 0x%x\n",
buffers[i]->id, buffers[i]->size, flags & BM_MEM_MASK);
newMem[i] = alloc_block(bm,
buffers[i]->size,
buffers[i]->alignment,
flags & BM_MEM_MASK);
if (!newMem[i])
goto cleanup;
}
}
/* Now copy all the image data and free the old texture memory.
*/
for (i = 0; i < nr; i++) {
if (newMem[i]) {
if (buffers[i]->block) {
/* XXX: To be replaced with DMA, GTT bind, and other
* mechanisms in final version. Memcpy (or sse_memcpy) is
* probably pretty good for local->agp uploads.
*/
DBG("memcpy %d bytes\n", buffers[i]->size);
memcpy(newMem[i]->virtual,
buffers[i]->block->virtual,
buffers[i]->size);
free_block(bm, buffers[i]->block);
nr_uploads++;
}
buffers[i]->block = newMem[i];
buffers[i]->block->buf = buffers[i];
}
}
/* Tell hardware that its texture and other caches may be invalid:
*/
if (nr_uploads && (flags & (BM_MEM_AGP|BM_MEM_VRAM)))
bmFlushReadCaches(bm);
DBG("%s - success\n", __FUNCTION__);
return 1;
cleanup:
/* Release any allocations made prior to failure:
*/
for (i = 0; i < nr; i++) {
if (newMem[i])
free_block(bm, newMem[i]);
}
_mesa_printf("%s - fail\n", __FUNCTION__);
return 0;
}
static unsigned evict_lru( struct bufmgr *bm,
unsigned flags)
{
int i;
DBG("%s\n", __FUNCTION__);
if (flags & BM_NO_EVICT)
return 0;
/* XXX: this is broken with >1 active pool - all the first pool
* will be evicted before starting on the second. Actually, maybe
* you want that in some situations...
*/
for (i = 0; i < bm->nr_pools; i++) {
if ((bm->pool[i].flags & flags & BM_MEM_MASK) &&
!(bm->pool[i].flags & BM_NO_EVICT)) {
struct block *block = bm->pool[i].lru.next;
unsigned size = block->buf->size;
if (block == &bm->pool[i].lru ||
!bmTestFence(bm, block->fence))
return 0;
move_buffers(bm, &block->buf, 1, BM_MEM_LOCAL);
return size;
}
}
return 0;
}
#if 0
/* Speculatively move texture images which haven't been used in a
* while back to local memory.
*/
static void viaSwapOutWork( struct bufmgr *bm )
{
unsigned total = 0;
unsigned target;
if (bm->thrashing) {
target = 1*1024*1024;
}
else if (bmIsTexMemLow(bm)) {
target = 64*1024;
}
else {
return;
}
while (1) {
unsigned size = evict_lru(bm);
if (!size)
return;
total += size;
if (total >= target)
return;
}
}
#endif
/***********************************************************************
* Public functions
*/
/* The initialization functions are skewed in the fake implementation.
* This call would be to attach to an existing manager, rather than to
* create a local one.
*/
struct bufmgr *bm_fake_intel_Attach( struct intel_context *intel )
{
struct bufmgr *bm = (struct bufmgr *)calloc(sizeof(*bm), 1);
bm->intel = intel;
bm->hash = _mesa_NewHashTable();
return bm;
}
void bmInitMemType( struct bufmgr *bm,
unsigned mem_type,
unsigned long size )
{
/* Nothing really to do. Could store and use to validate
* bmInitPool requests.
*/
}
/* The virtual pointer would go away in a true implementation.
*/
int bmInitPool( struct bufmgr *bm,
unsigned long low_offset,
void *low_virtual,
unsigned long size,
unsigned flags)
{
GLuint i;
if (bm->nr_pools >= BM_POOL_MAX)
return -1;
i = bm->nr_pools++;
DBG("bmInitPool %d low_offset %x sz %x\n",
i, low_offset, size);
bm->pool[i].heap = mmInit( low_offset, size );
bm->pool[i].virtual = low_virtual - low_offset;
bm->pool[i].flags = flags;
make_empty_list(&bm->pool[i].lru);
make_empty_list(&bm->pool[i].freed);
return i;
}
void bmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers)
{
unsigned i;
for (i = 0; i < n; i++) {
struct buffer *buf = calloc(sizeof(*buf), 1);
buf->id = ++bm->buf_nr;
buf->alignment = 12; /* page-alignment to fit in with AGP swapping */
buf->flags = BM_MEM_AGP|BM_MEM_VRAM|BM_MEM_LOCAL;
buffers[i] = buf->id;
_mesa_HashInsert(bm->hash, buffers[i], buf);
}
}
void bmDeleteBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers)
{
unsigned i;
for (i = 0; i < n; i++) {
struct buffer *buf = _mesa_HashLookup(bm->hash, buffers[i]);
if (buf) {
free_block(bm, buf->block);
free(buf);
_mesa_HashRemove(bm->hash, buffers[i]);
}
assert(_mesa_HashLookup(bm->hash, buffers[i]) == NULL);
}
}
/* Hook to inform faked buffer manager about fixed-position
* front,depth,back buffers. These may move to a fully memory-managed
* scheme, or they may continue to be managed as is. It will probably
* be useful to pass a fixed offset here one day.
*/
unsigned bmBufferStatic(struct bufmgr *bm,
unsigned buffer,
unsigned size,
unsigned pool )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
assert(!buf->block);
assert(bm->pool[pool].flags & BM_NO_EVICT);
assert(bm->pool[pool].flags & BM_NO_MOVE);
buf->size = size;
buf->flags = bm->pool[pool].flags;
buf->alignment = 12;
buf->block = alloc_from_pool(bm, pool, buf->size, buf->alignment);
if (!buf->block)
return 0;
buf->block->buf = buf;
return buf->block->mem->ofs;
}
/* If buffer size changes, free and reallocate. Otherwise update in
* place.
*/
void bmBufferData(struct bufmgr *bm,
unsigned buffer,
unsigned size,
const void *data,
unsigned flags )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
DBG("bmBufferData %d sz 0x%x data: %p\n", buffer, size, data);
assert(!buf->mapped);
if (buf->block) {
if ((buf->block->mem_type != BM_MEM_LOCAL && !bmTestFence(bm, buf->block->fence)) ||
(buf->size && buf->size != size) ||
(data == NULL)) {
free_block(bm, buf->block);
buf->block = NULL;
}
}
buf->size = size;
if (data != NULL) {
bmAllocMem(bm, buf, buf->flags | flags);
memcpy(buf->block->virtual, data, size);
}
}
/* Update the buffer in place, in whatever space it is currently resident:
*/
void bmBufferSubData(struct bufmgr *bm,
unsigned buffer,
unsigned offset,
unsigned size,
const void *data )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);
if (buf->block == 0)
bmAllocMem(bm, buf, buf->flags);
if (buf->block->mem_type != BM_MEM_LOCAL)
bmFinishFence(bm, buf->block->fence);
if (size)
memcpy(buf->block->virtual + offset, data, size);
}
/* Return a pointer to whatever space the buffer is currently resident in:
*/
void *bmMapBuffer( struct bufmgr *bm,
unsigned buffer,
unsigned flags )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
DBG("bmMapBuffer %d\n", buffer);
if (buf->mapped)
return NULL;
if (buf->block == 0)
bmAllocMem(bm, buf, flags);
if (buf->block == 0)
return NULL;
buf->mapped = 1;
/* Finish any outstanding operations to/from this memory:
*/
if (buf->block->mem_type != BM_MEM_LOCAL)
bmFinishFence(bm, buf->block->fence);
return buf->block->virtual;
}
void bmUnmapBuffer( struct bufmgr *bm, unsigned buffer )
{
struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer );
DBG("bmUnmapBuffer %d\n", buffer);
buf->mapped = 0;
}
/* Add a mechanism to tell the manager about some fixed buffers such
* as the (fixed) front, back and depth buffers. Something like this
* may be needed even in a finalized version if we keep the static
* management of these buffers.
*
* These are excluded from the buffer memory management in this file,
* but are presented to the driver by the same interface. In the
* future they may become managed.
*/
#if 0
void bm_fake_SetFixedBufferParams( struct bufmgr *bm
unsigned buffer,
unsigned offset,
unsigned size )
{
}
#endif
/* Build the list of buffers to validate:
*/
struct bm_buffer_list *bmNewBufferList( void )
{
struct bm_buffer_list *list = calloc(sizeof(*list), 1);
DBG("bmNewBufferList\n");
return list;
}
void bmAddBuffer( struct bm_buffer_list *list,
unsigned buffer,
unsigned flags,
unsigned *memtype_return,
unsigned *offset_return )
{
assert(list->nr < BM_LIST_MAX);
list->elem[list->nr].buffer = buffer;
list->elem[list->nr].memtype_return = memtype_return;
list->elem[list->nr].offset_return = offset_return;
DBG("bmAddBuffer nr %d buf %d\n",
list->nr, buffer);
list->nr++;
}
void bmFreeBufferList( struct bm_buffer_list *list )
{
free(list);
}
/* To be called prior to emitting commands to hardware which reference
* these buffers. The buffer_usage list provides information on where
* the buffers should be placed and whether their contents need to be
* preserved on copying. The offset and pool data elements are return
* values from this function telling the driver exactly where the
* buffers are currently located.
*/
int bmValidateBufferList( struct bufmgr *bm,
struct bm_buffer_list *list,
unsigned flags )
{
struct buffer *bufs[BM_LIST_MAX];
unsigned i;
DBG("%s\n", __FUNCTION__);
if (list->nr > BM_LIST_MAX)
return 0;
for (i = 0; i < list->nr; i++)
bufs[i] = _mesa_HashLookup(bm->hash, list->elem[i].buffer);
/* The old story: evict one texture after another until allocation
* succeeds. This is a pretty poor strategy but really hard to do
* better without more infrastucture... Which is coming - hooray!
*/
while (!move_buffers(bm, bufs, list->nr, flags)) {
if (!delayed_free(bm) &&
!evict_lru(bm, flags))
return 0;
_mesa_printf("couldn't allocate sufficient texture memory\n");
exit(1);
}
for (i = 0; i < list->nr; i++) {
DBG("%d: buf %d ofs 0x%x\n",
i, bufs[i]->id, bufs[i]->block->mem->ofs);
assert(!bufs[i]->mapped);
if (list->elem[i].offset_return)
list->elem[i].offset_return[0] = bufs[i]->block->mem->ofs;
if (list->elem[i].memtype_return)
list->elem[i].memtype_return[0] = bufs[i]->block->mem_type;
}
return 1;
}
/* After commands are emitted but before unlocking, this must be
* called so that the buffer manager can correctly age the buffers.
* The buffer manager keeps track of the list of validated buffers, so
* already knows what to apply the fence to.
*
* The buffer manager knows how to emit and test fences directly
* through the drm and without callbacks or whatever into the driver.
*/
unsigned bmFenceBufferList( struct bufmgr *bm, struct bm_buffer_list *list )
{
DBG("%s (%d bufs)\n", __FUNCTION__, list->nr);
if (list->nr) {
unsigned i;
unsigned fence = bmSetFence( bm );
/* Move all buffers to head of resident list and set their fences
*/
for (i = 0; i < list->nr; i++) {
struct buffer *buf = _mesa_HashLookup(bm->hash, list->elem[i].buffer);
move_to_head(&buf->block->pool->lru, buf->block);
buf->block->fence = fence;
}
return fence;
}
else
return 0;
}
/* This functionality is used by the buffer manager, not really sure
* if we need to be exposing it in this way, probably libdrm will
* offer equivalent calls.
*
* For now they can stay, but will likely change/move before final:
*/
unsigned bmSetFence( struct bufmgr *bm )
{
assert(bm->intel->locked);
return intelEmitIrqLocked( bm->intel );
}
int bmTestFence( struct bufmgr *bm, unsigned fence )
{
/* if (fence % 1024 == 0) */
/* _mesa_printf("%d %d\n", fence, bm->intel->sarea->last_dispatch); */
return fence <= bm->intel->sarea->last_dispatch;
}
void bmFinishFence( struct bufmgr *bm, unsigned fence )
{
if (!bmTestFence(bm, fence))
intelWaitIrq( bm->intel, fence );
}
/* There is a need to tell the hardware to flush various caches
* before we can start reading and writing video memory.
*
* TODO: Need a flag value to tell hardware which caches have changed?
* Who would we rely on to populate the flag?
*/
/* If new data is uploaded/mapped to video or agp memory, need to
* flush the texture and other read caches to ensure the new version
* is picked up. Can be done immediately after the upload (ie. within
* ValidateBuffers).
*/
void bmFlushReadCaches( struct bufmgr *bm )
{
}
/* If a buffer which has been written to is going to be evicted, read
* by bmGetBufferData or mappped with bmMapBuffer, need to flush the
* write cache first. Probably want to make sure this happens
* immediately after the last write and before the fence (how to
* tell?). If we wait until just prior the evict/read/map, would then
* have to emit another fence and wait for the hw queue to drain to be
* sure the caches had flushed.
*
* A possible strategy:
* - every once in a while, when there is no last_draw_flush_fence outstanding,
* emit a draw-cache flush just prior to the fence.
* - note the fence (last_draw_flush_fence)
* - note the most recently retired value of last_draw_flush_fence in
* last_retired_draw_flush_fence
* - keep track of which fence each buffer is last written to in
* buffer.last_write_fence
* - on evict/read/map, check:
* - if buffer.last_write_fence > last_draw_flush_fence {
* emit_flush
* last_draw_flush_fence = emit fence
* }
* if last_write_fence > last_retired_draw_flush_fence {
* finish_fence(last_draw_flush_fence)
* last_retired_draw_flush_fence = last_draw_fence
* }
*
*/
void bmFlushDrawCache( struct bufmgr *bm )
{
}
/* Specifically ignore texture memory sharing.
*/
void bm_fake_NotifyContendedLockTake( struct bufmgr *bm )
{
fprintf(stderr, "did we just lose texture memory? oh well, never mind\n");
}

View File

@@ -59,7 +59,7 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
{
struct dd_function_table functions;
i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context);
intelContextPtr intel = &i830->intel;
struct intel_context *intel = &i830->intel;
GLcontext *ctx = &intel->ctx;
if (!i830) return GL_FALSE;

View File

@@ -48,10 +48,8 @@
*/
#define I830_DESTREG_CBUFADDR0 0
#define I830_DESTREG_CBUFADDR1 1
#define I830_DESTREG_CBUFADDR2 2
#define I830_DESTREG_DBUFADDR0 3
#define I830_DESTREG_DBUFADDR1 4
#define I830_DESTREG_DBUFADDR2 5
#define I830_DESTREG_DV0 6
#define I830_DESTREG_DV1 7
#define I830_DESTREG_SENABLE 8
@@ -160,7 +158,7 @@ i830CreateContext( const __GLcontextModes *mesaVis,
/* i830_tex.c, i830_texstate.c
*/
extern void
i830UpdateTextureState( intelContextPtr intel );
i830UpdateTextureState( struct intel_context *intel );
extern void
i830InitTextureFuncs( struct dd_function_table *functions );
@@ -206,7 +204,7 @@ i830TryTextureDrawPixels( GLcontext *ctx,
const GLvoid *pixels );
extern void
i830ClearWithTris( intelContextPtr intel, GLbitfield mask,
i830ClearWithTris( struct intel_context *intel, GLbitfield mask,
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);

View File

@@ -58,7 +58,7 @@ do { \
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void set_initial_state( i830ContextPtr i830 )
static void set_initial_state( struct intel_context *intel )
{
memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
i830->meta.active = ACTIVE;
@@ -66,7 +66,7 @@ static void set_initial_state( i830ContextPtr i830 )
}
static void set_no_depth_stencil_write( i830ContextPtr i830 )
static void set_no_depth_stencil_write( struct intel_context *intel )
{
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
*/
@@ -88,7 +88,7 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 )
/* Set stencil unit to replace always with the reference value.
*/
static void set_stencil_replace( i830ContextPtr i830,
static void set_stencil_replace( struct intel_context *intel,
GLuint s_mask,
GLuint s_clear)
{
@@ -140,7 +140,7 @@ static void set_stencil_replace( i830ContextPtr i830,
}
static void set_color_mask( i830ContextPtr i830, GLboolean state )
static void set_color_mask( struct intel_context *intel, GLboolean state )
{
const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
(1 << WRITEMASK_GREEN_SHIFT) |
@@ -161,7 +161,7 @@ static void set_color_mask( i830ContextPtr i830, GLboolean state )
/* Installs a one-stage passthrough texture blend pipeline. Is there
* more that can be done to turn off texturing?
*/
static void set_no_texture( i830ContextPtr i830 )
static void set_no_texture( struct intel_context *intel )
{
static const struct gl_tex_env_combine_state comb = {
GL_NONE, GL_NONE,
@@ -181,7 +181,7 @@ static void set_no_texture( i830ContextPtr i830 )
/* Set up a single element blend stage for 'replace' texturing with no
* funny ops.
*/
static void enable_texture_blend_replace( i830ContextPtr i830,
static void enable_texture_blend_replace( struct intel_context *intel,
GLenum format )
{
static const struct gl_tex_env_combine_state comb = {
@@ -207,7 +207,7 @@ static void enable_texture_blend_replace( i830ContextPtr i830,
/* Set up an arbitary piece of memory as a rectangular texture
* (including the front or back buffer).
*/
static void set_tex_rect_source( i830ContextPtr i830,
static void set_tex_rect_source( struct intel_context *intel,
GLuint offset,
GLuint width,
GLuint height,
@@ -249,17 +249,17 @@ static void set_tex_rect_source( i830ContextPtr i830,
/* Select between front and back draw buffers.
*/
static void set_draw_offset( i830ContextPtr i830,
static void set_draw_offset( struct intel_context *intel,
GLuint offset )
{
i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset;
/* i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset; */
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
}
/* Setup an arbitary draw format, useful for targeting
* texture or agp memory.
*/
static void set_draw_format( i830ContextPtr i830,
static void set_draw_format( struct intel_context *intel,
GLuint format,
GLuint depth_format)
{
@@ -271,7 +271,7 @@ static void set_draw_format( i830ContextPtr i830,
}
static void set_vertex_format( i830ContextPtr i830 )
static void set_vertex_format( struct intel_context *intel )
{
i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
VFT0_TEX_COUNT(1) |
@@ -287,446 +287,6 @@ static void set_vertex_format( i830ContextPtr i830 )
}
static void draw_quad(i830ContextPtr i830,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
{
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
PRIM3D_TRIFAN,
4*vertex_size,
vertex_size );
intelVertex tmp;
int i;
/* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
/* __FUNCTION__, */
/* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
/* initial vertex, left bottom */
tmp.v.x = x0;
tmp.v.y = y0;
tmp.v.z = 1.0;
tmp.v.w = 1.0;
tmp.v.color.red = red;
tmp.v.color.green = green;
tmp.v.color.blue = blue;
tmp.v.color.alpha = alpha;
tmp.v.specular.red = 0;
tmp.v.specular.green = 0;
tmp.v.specular.blue = 0;
tmp.v.specular.alpha = 0;
tmp.v.u0 = s0;
tmp.v.v0 = t0;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* right bottom */
vb += 8;
tmp.v.x = x1;
tmp.v.u0 = s1;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* right top */
vb += 8;
tmp.v.y = y1;
tmp.v.v0 = t1;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* left top */
vb += 8;
tmp.v.x = x0;
tmp.v.u0 = s0;
for (i = 0 ; i < 8 ; i++)
vb[i] = tmp.ui[i];
/* fprintf(stderr, "%s: DV1: %x\n", */
/* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
}
void
i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
i830ContextPtr i830 = I830_CONTEXT( intel );
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelScreenPrivate *screen = intel->intelScreen;
int x0, y0, x1, y1;
SET_STATE( i830, meta );
set_initial_state( i830 );
set_no_texture( i830 );
set_vertex_format( i830 );
LOCK_HARDWARE(intel);
if(!all) {
x0 = cx;
y0 = cy;
x1 = x0 + cw;
y1 = y0 + ch;
} else {
x0 = 0;
y0 = 0;
x1 = x0 + dPriv->w;
y1 = y0 + dPriv->h;
}
/* Don't do any clipping to screen - these are window coordinates.
* The active cliprects will be applied as for any other geometry.
*/
if(mask & BUFFER_BIT_FRONT_LEFT) {
set_no_depth_stencil_write( i830 );
set_color_mask( i830, GL_TRUE );
set_draw_offset( i830, screen->front.offset );
draw_quad(i830, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & BUFFER_BIT_BACK_LEFT) {
set_no_depth_stencil_write( i830 );
set_color_mask( i830, GL_TRUE );
set_draw_offset( i830, screen->back.offset );
draw_quad(i830, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if(mask & BUFFER_BIT_STENCIL) {
set_stencil_replace( i830,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
set_color_mask( i830, GL_FALSE );
set_draw_offset( i830, screen->front.offset );
draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
}
UNLOCK_HARDWARE(intel);
SET_STATE( i830, state );
}
GLboolean
i830TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
i830ContextPtr i830 = I830_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = i830->intel.intelScreen;
GLint pitch = pack->RowLength ? pack->RowLength : width;
__DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
int textureFormat;
GLenum glTextureFormat;
int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
int destFormat, depthFormat, destPitch;
drm_clip_rect_t tmp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( ctx->_ImageTransferState ||
pack->SwapBytes ||
pack->LsbFirst ||
!pack->Invert) {
fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
return GL_FALSE;
}
switch (screen->fbFormat) {
case DV_PF_565:
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
glTextureFormat = GL_RGB;
break;
case DV_PF_555:
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
glTextureFormat = GL_RGBA;
break;
case DV_PF_8888:
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
glTextureFormat = GL_RGBA;
break;
default:
fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
screen->fbFormat);
return GL_FALSE;
}
switch (type) {
case GL_UNSIGNED_SHORT_5_6_5:
if (format != GL_RGB) return GL_FALSE;
destFormat = COLR_BUF_RGB565;
depthFormat = DEPTH_FRMT_16_FIXED;
destPitch = pitch * 2;
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
if (format != GL_BGRA) return GL_FALSE;
destFormat = COLR_BUF_ARGB8888;
depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
destPitch = pitch * 4;
break;
default:
fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(type));
return GL_FALSE;
}
destFormat |= (0x02<<24);
/* fprintf(stderr, "type: %s destFormat: %x\n", */
/* _mesa_lookup_enum_by_nr(type), */
/* destFormat); */
intelFlush( ctx );
SET_STATE( i830, meta );
set_initial_state( i830 );
set_no_depth_stencil_write( i830 );
LOCK_HARDWARE( intel );
{
intelWaitForIdle( intel ); /* required by GL */
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
#if 0
/* FIXME -- Just emit the correct state
*/
if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,
destPitch) != 0) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
return GL_FALSE;
}
#endif
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
/* Set the frontbuffer up as a large rectangular texture.
*/
set_tex_rect_source( i830,
src_offset,
screen->width,
screen->height,
screen->front.pitch,
textureFormat );
enable_texture_blend_replace( i830, glTextureFormat );
/* Set the 3d engine to draw into the agp memory
*/
set_draw_offset( i830, destOffset );
set_draw_format( i830, destFormat, depthFormat );
/* Draw a single quad, no cliprects:
*/
i830->intel.numClipRects = 1;
i830->intel.pClipRects = &tmp;
i830->intel.pClipRects[0].x1 = 0;
i830->intel.pClipRects[0].y1 = 0;
i830->intel.pClipRects[0].x2 = width;
i830->intel.pClipRects[0].y2 = height;
draw_quad( i830,
0, width, 0, height,
0, 255, 0, 0,
x, x+width, y, y+height );
intelWindowMoved( intel );
}
UNLOCK_HARDWARE( intel );
intelFinish( ctx ); /* required by GL */
SET_STATE( i830, state );
return GL_TRUE;
}
GLboolean
i830TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
i830ContextPtr i830 = I830_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int textureFormat;
GLenum glTextureFormat;
int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Todo -- upload images that aren't in agp space, then texture
* from them.
*/
if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
return GL_FALSE;
}
/* Todo -- don't want to clobber all the drawing state like we do
* for readpixels -- most of this state can be handled just fine.
*/
if ( ctx->_ImageTransferState ||
unpack->SwapBytes ||
unpack->LsbFirst ||
ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits) {
fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
return GL_FALSE;
}
/* Todo -- remove these restrictions:
*/
if (ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != -1.0F)
return GL_FALSE;
switch (type) {
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
if (format != GL_BGRA) return GL_FALSE;
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
glTextureFormat = GL_RGBA;
break;
case GL_UNSIGNED_SHORT_5_6_5:
if (format != GL_RGB) return GL_FALSE;
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
glTextureFormat = GL_RGB;
break;
case GL_UNSIGNED_SHORT_8_8_MESA:
if (format != GL_YCBCR_MESA) return GL_FALSE;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY
/* | TM0S1_COLORSPACE_CONVERSION */
);
glTextureFormat = GL_YCBCR_MESA;
break;
case GL_UNSIGNED_SHORT_8_8_REV_MESA:
if (format != GL_YCBCR_MESA) return GL_FALSE;
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL
/* | TM0S1_COLORSPACE_CONVERSION */
);
glTextureFormat = GL_YCBCR_MESA;
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
if (format != GL_BGRA) return GL_FALSE;
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
glTextureFormat = GL_RGBA;
break;
default:
fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
return GL_FALSE;
}
intelFlush( ctx );
SET_STATE( i830, meta );
LOCK_HARDWARE( intel );
{
intelWaitForIdle( intel ); /* required by GL */
y -= height; /* cope with pixel zoom */
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
set_initial_state( i830 );
/* Set the pixel image up as a rectangular texture.
*/
set_tex_rect_source( i830,
src_offset,
width,
height,
pitch, /* XXXX!!!! -- /2 sometimes */
textureFormat );
enable_texture_blend_replace( i830, glTextureFormat );
/* Draw to the current draw buffer:
*/
set_draw_offset( i830, dst_offset );
/* Draw a quad, use regular cliprects
*/
/* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
draw_quad( i830,
x, x+width, y, y+height,
0, 255, 0, 0,
0, width, 0, height );
intelWindowMoved( intel );
}
UNLOCK_HARDWARE( intel );
intelFinish( ctx ); /* required by GL */
SET_STATE(i830, state);
return GL_TRUE;
}

View File

@@ -407,10 +407,10 @@
#define LOGICOP_SET 0xf
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
#define ENABLE_STENCIL_TEST_MASK (1<<17)
#define STENCIL_TEST_MASK(x) ((x)<<8)
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8)
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
#define STENCIL_WRITE_MASK(x) (x)
#define STENCIL_WRITE_MASK(x) ((x)&0xff)
/* _3DSTATE_MODES_5, p196 */
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))

View File

@@ -1012,13 +1012,12 @@ static void i830_init_packets( i830ContextPtr i830 )
(BUF_3D_ID_DEPTH |
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) |
BUF_3D_USE_FENCE);
i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset;
/* i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; */
i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
switch (screen->fbFormat) {
case DV_PF_555:
case DV_PF_565:
i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */

View File

@@ -200,7 +200,7 @@ intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj )
texObj->DriverData = t;
t->intel.base.tObj = texObj;
t->intel.dirty = I830_UPLOAD_TEX_ALL;
t->intel.dirty = ~0;
make_empty_list( &t->intel.base );
t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */
@@ -268,7 +268,7 @@ static void i830TexParameter( GLcontext *ctx, GLenum target,
return;
}
t->intel.dirty = I830_UPLOAD_TEX_ALL;
t->intel.dirty = ~0;
}

View File

@@ -101,7 +101,7 @@ static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count,
}
static __inline__ GLuint GetTexelOp(GLint unit)
static inline GLuint GetTexelOp(GLint unit)
{
switch(unit) {
case 0: return TEXBLENDARG_TEXEL0;

View File

@@ -246,7 +246,7 @@ static GLboolean i830SetTexImages( i830ContextPtr i830,
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
t->intel.dirty = I830_UPLOAD_TEX_ALL;
t->intel.dirty = ~0;
return intelUploadTexImages( &i830->intel, &t->intel, 0 );
}
@@ -259,11 +259,7 @@ static void i830_import_tex_unit( i830ContextPtr i830,
if(INTEL_DEBUG&DEBUG_TEXTURE)
fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
if (i830->intel.CurrentTexObj[unit])
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
t->intel.base.bound |= (1 << unit);
I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
@@ -285,7 +281,7 @@ static void i830_import_tex_unit( i830ContextPtr i830,
i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE];
i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
t->intel.dirty &= ~(1<<unit); /* This is broken! */
}
@@ -317,7 +313,7 @@ static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
* time.
*/
if (i830->intel.CurrentTexObj[unit] != &t->intel ||
(t->intel.dirty & I830_UPLOAD_TEX(unit))) {
(t->intel.dirty & (1<<unit))) {
i830_import_tex_unit( i830, t, unit);
}
@@ -419,14 +415,10 @@ static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
* one if nothing is enabled.
*/
if ( i830->intel.CurrentTexObj[unit] != NULL ) {
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
i830->intel.CurrentTexObj[unit] = NULL;
}
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
i830->intel.CurrentTexObj[unit] = NULL;
return GL_TRUE;
}
@@ -436,7 +428,7 @@ static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
if (texUnit->_ReallyEnabled &&
INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024)
intel_context(ctx)->intelScreen->tex.size < 2048 * 1024)
return GL_FALSE;
switch(texUnit->_ReallyEnabled) {
@@ -458,7 +450,7 @@ static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
}
void i830UpdateTextureState( intelContextPtr intel )
void i830UpdateTextureState( struct intel_context *intel )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
GLcontext *ctx = &intel->ctx;

View File

@@ -34,7 +34,7 @@
#include "tnl/t_context.h"
#include "tnl/t_vertex.h"
static GLboolean i830_check_vertex_size( intelContextPtr intel,
static GLboolean i830_check_vertex_size( struct intel_context *intel,
GLuint expected );
#define SZ_TO_HW(sz) ((sz-2)&0x3)
@@ -59,7 +59,7 @@ do { \
#define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
#define TEXBIND_SET(n, x) ((x)<<((n)*4))
static void i830_render_start( intelContextPtr intel )
static void i830_render_start( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
i830ContextPtr i830 = I830_CONTEXT(intel);
@@ -186,7 +186,7 @@ static void i830_render_start( intelContextPtr intel )
}
}
static void i830_reduced_primitive_state( intelContextPtr intel,
static void i830_reduced_primitive_state( struct intel_context *intel,
GLenum rprim )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
@@ -217,7 +217,7 @@ static void i830_reduced_primitive_state( intelContextPtr intel,
/* Pull apart the vertex format registers and figure out how large a
* vertex is supposed to be.
*/
static GLboolean i830_check_vertex_size( intelContextPtr intel,
static GLboolean i830_check_vertex_size( struct intel_context *intel,
GLuint expected )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
@@ -257,11 +257,11 @@ static GLboolean i830_check_vertex_size( intelContextPtr intel,
return sz == expected;
}
static void i830_emit_invarient_state( intelContextPtr intel )
static void i830_emit_invarient_state( struct intel_context *intel )
{
BATCH_LOCALS;
BEGIN_BATCH( 200 );
BEGIN_BATCH(200, 0);
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
@@ -355,7 +355,7 @@ static void i830_emit_invarient_state( intelContextPtr intel )
#define emit( intel, state, size ) \
do { \
int k; \
BEGIN_BATCH( size / sizeof(GLuint)); \
BEGIN_BATCH(size / sizeof(GLuint), 0); \
for (k = 0 ; k < size / sizeof(GLuint) ; k++) \
OUT_BATCH(state[k]); \
ADVANCE_BATCH(); \
@@ -364,7 +364,7 @@ do { \
/* Push the state into the sarea and/or texture memory.
*/
static void i830_emit_state( intelContextPtr intel )
static void i830_emit_state( struct intel_context *intel )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
struct i830_hw_state *state = i830->current;
@@ -405,32 +405,32 @@ static void i830_emit_state( intelContextPtr intel )
state->emitted |= dirty;
}
static void i830_destroy_context( intelContextPtr intel )
static void i830_destroy_context( struct intel_context *intel )
{
_tnl_free_vertices(&intel->ctx);
}
static void i830_set_draw_offset( intelContextPtr intel, int offset )
static void i830_set_draw_offset( struct intel_context *intel, int offset )
{
i830ContextPtr i830 = I830_CONTEXT(intel);
I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset;
/* i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset; */
}
/* This isn't really handled at the moment.
*/
static void i830_lost_hardware( intelContextPtr intel )
static void i830_lost_hardware( struct intel_context *intel )
{
I830_CONTEXT(intel)->state.emitted = 0;
}
static void i830_emit_flush( intelContextPtr intel )
static void i830_emit_flush( struct intel_context *intel )
{
BATCH_LOCALS;
BEGIN_BATCH(2);
BEGIN_BATCH(2, 0);
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );
OUT_BATCH( 0 );
ADVANCE_BATCH();
@@ -441,7 +441,6 @@ static void i830_emit_flush( intelContextPtr intel )
void i830InitVtbl( i830ContextPtr i830 )
{
i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj;
i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
i830->intel.vtbl.clear_with_tris = i830ClearWithTris;
i830->intel.vtbl.destroy = i830_destroy_context;

View File

@@ -41,6 +41,10 @@
#include "utils.h"
#include "i915_reg.h"
#include "bufmgr.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
/***************************************
* Mesa's Driver Functions
***************************************/
@@ -65,7 +69,7 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state )
_ac_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_tnl_invalidate_vertex_state( ctx, new_state );
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
intel_context(ctx)->NewGLState |= new_state;
/* Todo: gather state values under which tracked parameters become
* invalidated, add callbacks for things like
@@ -99,13 +103,16 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
void *sharedContextPrivate)
{
struct dd_function_table functions;
i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context);
intelContextPtr intel = &i915->intel;
struct i915_context *i915 = (struct i915_context *) CALLOC_STRUCT(i915_context);
struct intel_context *intel = &i915->intel;
GLcontext *ctx = &intel->ctx;
if (!i915) return GL_FALSE;
_mesa_printf( "\ntexmem branch (i915, drop2)\n\n");
i915InitVtbl( i915 );
i915InitMetaFuncs( i915 );
i915InitDriverFunctions( &functions );
@@ -119,48 +126,28 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS;
ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS;
intel->nr_heaps = 1;
intel->texture_heaps[0] =
driCreateTextureHeap( 0, intel,
intel->intelScreen->tex.size,
12,
I830_NR_TEX_REGIONS,
intel->sarea->texList,
& intel->sarea->texAge,
& intel->swapped,
sizeof( struct i915_texture_object ),
(destroy_texture_object_t *)intelDestroyTexObj );
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are
* tightly packed, but they're not in Intel graphics
* hardware.
/* Advertise the full hardware capabilities. The new memory
* manager should cope much better with overload situations:
*/
ctx->Const.MaxTextureUnits = 1;
driCalculateMaxTextureLevels( intel->texture_heaps,
intel->nr_heaps,
&intel->ctx.Const,
4,
11, /* max 2D texture size is 2048x2048 */
8, /* 3D texture */
11, /* cube texture. */
11, /* rect texture */
12,
GL_FALSE );
ctx->Const.MaxTextureLevels = 12;
ctx->Const.Max3DTextureLevels = 9;
ctx->Const.MaxCubeTextureLevels = 12;
ctx->Const.MaxTextureRectSize = (1<<11);
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
/* GL_ARB_fragment_program limits - don't think Mesa actually
* validates programs against these, and in any case one ARB
* instruction can translate to more than one HW instruction, so
* we'll still have to check and fallback each time.
*/
*/
ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY;
ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */
ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT;
ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN;
ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN;
ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +
I915_MAX_TEX_INSN);
I915_MAX_TEX_INSN);
ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT;
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */

View File

@@ -43,6 +43,7 @@
#define I915_UPLOAD_PROGRAM 0x8
#define I915_UPLOAD_CONSTANTS 0x10
#define I915_UPLOAD_FOG 0x20
#define I915_UPLOAD_INVARIENT 0x40
#define I915_UPLOAD_TEX(i) (0x00010000<<(i))
#define I915_UPLOAD_TEX_ALL (0x00ff0000)
#define I915_UPLOAD_TEX_0_SHIFT 16
@@ -52,10 +53,8 @@
*/
#define I915_DESTREG_CBUFADDR0 0
#define I915_DESTREG_CBUFADDR1 1
#define I915_DESTREG_CBUFADDR2 2
#define I915_DESTREG_DBUFADDR0 3
#define I915_DESTREG_DBUFADDR1 4
#define I915_DESTREG_DBUFADDR2 5
#define I915_DESTREG_DV0 6
#define I915_DESTREG_DV1 7
#define I915_DESTREG_SENABLE 8
@@ -86,7 +85,6 @@
#define I915_STPREG_ST1 1
#define I915_STP_SETUP_SIZE 2
#define I915_TEXREG_MS2 0
#define I915_TEXREG_MS3 1
#define I915_TEXREG_MS4 2
#define I915_TEXREG_SS2 3
@@ -163,8 +161,6 @@ struct i915_fragment_program {
GLuint nr_params;
/* Helpers for i915_texprog.c:
*/
GLuint src_texture; /* Reg containing sampled texture color,
@@ -185,13 +181,6 @@ struct i915_fragment_program {
struct i915_texture_object
{
struct intel_texture_object intel;
GLenum lastTarget;
GLboolean refs_border_color;
GLuint Setup[I915_TEX_SETUP_SIZE];
};
#define I915_TEX_UNITS 8
@@ -206,6 +195,15 @@ struct i915_hw_state {
GLuint ConstantSize;
GLuint Program[I915_PROGRAM_SIZE];
GLuint ProgramSize;
/* Region pointers for relocation:
*/
struct intel_region *draw_region;
struct intel_region *depth_region;
struct intel_region *tex_region[I915_TEX_UNITS];
GLuint tex_offset[I915_TEX_UNITS];
GLuint active; /* I915_UPLOAD_* */
GLuint emitted; /* I915_UPLOAD_* */
};
@@ -220,6 +218,8 @@ struct i915_context
GLuint last_ReallyEnabled;
GLuint vertex_fog;
GLuint lodbias_ss2[MAX_TEXTURE_UNITS];
struct i915_fragment_program tex_program;
struct i915_fragment_program *current_program;
@@ -228,24 +228,14 @@ struct i915_context
};
typedef struct i915_context *i915ContextPtr;
typedef struct i915_texture_object *i915TextureObjectPtr;
#define I915_CONTEXT(ctx) ((i915ContextPtr)(ctx))
#define I915_STATECHANGE(i915, flag) \
do { \
if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__); \
INTEL_FIREVERTICES( &(i915)->intel ); \
(i915)->state.emitted &= ~(flag); \
} while (0)
#define I915_ACTIVESTATE(i915, flag, mode) \
do { \
if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n", \
flag, mode, __FUNCTION__); \
INTEL_FIREVERTICES( &(i915)->intel ); \
if (mode) \
(i915)->state.active |= (flag); \
@@ -257,7 +247,7 @@ do { \
/*======================================================================
* i915_vtbl.c
*/
extern void i915InitVtbl( i915ContextPtr i915 );
extern void i915InitVtbl( struct i915_context *i915 );
@@ -294,7 +284,7 @@ extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
/*======================================================================
* i915_texprog.c
*/
extern void i915ValidateTextureProgram( i915ContextPtr i915 );
extern void i915ValidateTextureProgram( struct i915_context *i915 );
/*======================================================================
@@ -308,44 +298,43 @@ extern void i915_print_ureg( const char *msg, GLuint ureg );
* i915_state.c
*/
extern void i915InitStateFunctions( struct dd_function_table *functions );
extern void i915InitState( i915ContextPtr i915 );
extern void i915InitState( struct i915_context *i915 );
extern void i915_update_fog( GLcontext *ctx );
/*======================================================================
* i915_tex.c
*/
extern void i915UpdateTextureState( intelContextPtr intel );
extern void i915UpdateTextureState( struct intel_context *intel );
extern void i915InitTextureFuncs( struct dd_function_table *functions );
extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj );
/*======================================================================
* i915_metaops.c
*/
extern GLboolean
i915TryTextureReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
extern GLboolean
i915TryTextureDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
extern void
i915ClearWithTris( intelContextPtr intel, GLbitfield mask,
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
void i915InitMetaFuncs( struct i915_context *i915 );
/*======================================================================
* i915_fragprog.c
*/
extern void i915ValidateFragmentProgram( i915ContextPtr i915 );
extern void i915ValidateFragmentProgram( struct i915_context *i915 );
extern void i915InitFragProgFuncs( struct dd_function_table *functions );
/*======================================================================
* Inline conversion functions. These are better-typed than the
* macros used previously:
*/
static inline struct i915_context *
i915_context( GLcontext *ctx )
{
return (struct i915_context *)ctx;
}
#define I915_CONTEXT(ctx) i915_context(ctx)
#endif

View File

@@ -806,7 +806,7 @@ static void check_wpos( struct i915_fragment_program *p )
static void translate_program( struct i915_fragment_program *p )
{
i915ContextPtr i915 = I915_CONTEXT(p->ctx);
struct i915_context *i915 = I915_CONTEXT(p->ctx);
i915_init_program( i915, p );
check_wpos( p );
@@ -840,7 +840,7 @@ static void i915BindProgram( GLcontext *ctx,
struct program *prog )
{
if (target == GL_FRAGMENT_PROGRAM_ARB) {
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
struct i915_fragment_program *p = (struct i915_fragment_program *)prog;
if (i915->current_program == p)
@@ -896,7 +896,7 @@ static void i915DeleteProgram( GLcontext *ctx,
struct program *prog )
{
if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
struct i915_fragment_program *p = (struct i915_fragment_program *)prog;
if (i915->current_program == p)
@@ -940,10 +940,10 @@ static void i915ProgramStringNotify( GLcontext *ctx,
}
void i915ValidateFragmentProgram( i915ContextPtr i915 )
void i915ValidateFragmentProgram( struct i915_context *i915 )
{
GLcontext *ctx = &i915->intel.ctx;
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;

View File

@@ -34,39 +34,32 @@
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_ioctl.h"
#include "intel_regions.h"
#include "i915_context.h"
#include "i915_reg.h"
/* A large amount of state doesn't need to be uploaded.
*/
#define ACTIVE (I915_UPLOAD_PROGRAM | \
#define ACTIVE (I915_UPLOAD_INVARIENT | \
I915_UPLOAD_PROGRAM | \
I915_UPLOAD_STIPPLE | \
I915_UPLOAD_CTX | \
I915_UPLOAD_BUFFERS | \
I915_UPLOAD_TEX(0))
#define SET_STATE( i915, STATE ) \
#define SET_STATE( i915, STATE ) \
do { \
i915->current->emitted &= ~ACTIVE; \
i915->current = &i915->STATE; \
i915->current = &i915->STATE; \
i915->current->emitted &= ~ACTIVE; \
} while (0)
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void set_initial_state( i915ContextPtr i915 )
{
memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
i915->meta.active = ACTIVE;
i915->meta.emitted = 0;
}
static void set_no_depth_stencil_write( i915ContextPtr i915 )
static void meta_no_depth_stencil_write( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
*/
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
@@ -82,10 +75,11 @@ static void set_no_depth_stencil_write( i915ContextPtr i915 )
/* Set stencil unit to replace always with the reference value.
*/
static void set_stencil_replace( i915ContextPtr i915,
static void meta_stencil_replace( struct intel_context *intel,
GLuint s_mask,
GLuint s_clear)
{
struct i915_context *i915 = i915_context(&intel->ctx);
GLuint op = STENCILOP_REPLACE;
GLuint func = COMPAREFUNC_ALWAYS;
@@ -100,7 +94,6 @@ static void set_stencil_replace( i915ContextPtr i915,
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
S6_DEPTH_WRITE_ENABLE);
/* ctx->Driver.StencilMask( ctx, s_mask )
*/
i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
@@ -108,7 +101,6 @@ static void set_stencil_replace( i915ContextPtr i915,
i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
STENCIL_WRITE_MASK(s_mask));
/* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
*/
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
@@ -137,8 +129,9 @@ static void set_stencil_replace( i915ContextPtr i915,
}
static void set_color_mask( i915ContextPtr i915, GLboolean state )
static void meta_color_mask( struct intel_context *intel, GLboolean state )
{
struct i915_context *i915 = i915_context(&intel->ctx);
const GLuint mask = (S5_WRITEDISABLE_RED |
S5_WRITEDISABLE_GREEN |
S5_WRITEDISABLE_BLUE |
@@ -210,8 +203,10 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state )
static void set_no_texture( i915ContextPtr i915 )
static void meta_no_texture( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
static const GLuint prog[] = {
_3DSTATE_PIXEL_SHADER_PROGRAM,
@@ -240,9 +235,10 @@ static void set_no_texture( i915ContextPtr i915 )
i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
}
#if 0
static void enable_texture_blend_replace( i915ContextPtr i915 )
static void meta_texture_blend_replace( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
static const GLuint prog[] = {
_3DSTATE_PIXEL_SHADER_PROGRAM,
@@ -285,78 +281,86 @@ static void enable_texture_blend_replace( i915ContextPtr i915 )
/* Set up an arbitary piece of memory as a rectangular texture
* (including the front or back buffer).
*/
static void set_tex_rect_source( i915ContextPtr i915,
GLuint offset,
GLuint width,
GLuint height,
GLuint pitch,
static void meta_tex_rect_source( struct intel_context *intel,
struct intel_region *region,
GLuint textureFormat )
{
struct i915_context *i915 = i915_context(&intel->ctx);
GLuint unit = 0;
GLint numLevels = 1;
GLuint *state = i915->meta.Tex[0];
pitch *= i915->intel.intelScreen->cpp;
GLuint pitch = region->pitch * region->cpp;
/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
state[I915_TEXREG_MS2] = offset;
state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
((width - 1) << MS3_WIDTH_SHIFT) |
textureFormat |
MS3_USE_FENCE_REGS);
intel_region_release(intel, &i915->meta.tex_region[0]);
intel_region_reference(&i915->meta.tex_region[0], region);
i915->meta.tex_offset[0] = 0;
state[I915_TEXREG_MS3] = (((region->height - 1) << MS3_HEIGHT_SHIFT) |
((region->pitch - 1) << MS3_WIDTH_SHIFT) |
textureFormat |
MS3_USE_FENCE_REGS);
state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
MS4_CUBE_FACE_ENA_MASK |
((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
MS4_CUBE_FACE_ENA_MASK |
((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) |
(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
(FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
(FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
(unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
(TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
(TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
(unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
state[I915_TEXREG_SS4] = 0;
i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
}
#endif
/* Select between front and back draw buffers.
*/
static void set_draw_offset( i915ContextPtr i915,
GLuint offset )
static void meta_draw_region( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region )
{
i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset;
struct i915_context *i915 = i915_context(&intel->ctx);
intel_region_release(intel, &i915->meta.draw_region);
intel_region_release(intel, &i915->meta.depth_region);
intel_region_reference(&i915->meta.draw_region, draw_region);
intel_region_reference(&i915->meta.depth_region, depth_region);
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
}
#if 0
/* Setup an arbitary draw format, useful for targeting texture or agp
* memory.
*/
static void set_draw_format( i915ContextPtr i915,
static void set_draw_format( struct intel_context *intel,
GLuint format,
GLuint depth_format)
{
struct i915_context *i915 = i915_context(&intel->ctx);
i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
format |
LOD_PRECLAMP_OGL |
TEX_DEFAULT_COLOR_OGL |
depth_format);
DSTORG_VERT_BIAS(0x8) | /* .5 */
format |
LOD_PRECLAMP_OGL |
TEX_DEFAULT_COLOR_OGL |
depth_format);
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
/* fprintf(stderr, "%s: DV1: %x\n", */
/* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
}
#endif
static void set_vertex_format( i915ContextPtr i915 )
static void set_vertex_format( struct intel_context *intel )
{
struct i915_context *i915 = i915_context(&intel->ctx);
i915->meta.Ctx[I915_CTXREG_LIS2] =
(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
@@ -371,146 +375,50 @@ static void set_vertex_format( i915ContextPtr i915 )
i915->meta.Ctx[I915_CTXREG_LIS4] |=
(S4_VFMT_COLOR |
S4_VFMT_SPEC_FOG |
S4_VFMT_XYZW);
S4_VFMT_XYZ);
i915->meta.emitted &= ~I915_UPLOAD_CTX;
}
static void draw_quad(i915ContextPtr i915,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1 )
/* Operations where the 3D engine is decoupled temporarily from the
* current GL state and used for other purposes than simply rendering
* incoming triangles.
*/
static void install_meta_state( struct intel_context *intel )
{
GLuint vertex_size = 8;
GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
PRIM3D_TRIFAN,
4 * vertex_size,
vertex_size );
intelVertex tmp;
int i;
struct i915_context *i915 = i915_context(&intel->ctx);
memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
i915->meta.active = ACTIVE;
i915->meta.emitted = 0;
if (0)
fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
__FUNCTION__,
x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
/* initial vertex, left bottom */
tmp.v.x = x0;
tmp.v.y = y0;
tmp.v.z = 1.0;
tmp.v.w = 1.0;
tmp.v.color.red = red;
tmp.v.color.green = green;
tmp.v.color.blue = blue;
tmp.v.color.alpha = alpha;
tmp.v.specular.red = 0;
tmp.v.specular.green = 0;
tmp.v.specular.blue = 0;
tmp.v.specular.alpha = 0;
tmp.v.u0 = s0;
tmp.v.v0 = t0;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* right bottom */
vb += vertex_size;
tmp.v.x = x1;
tmp.v.u0 = s1;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* right top */
vb += vertex_size;
tmp.v.y = y1;
tmp.v.v0 = t1;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
/* left top */
vb += vertex_size;
tmp.v.x = x0;
tmp.v.u0 = s0;
for (i = 0 ; i < vertex_size ; i++)
vb[i] = tmp.ui[i];
SET_STATE(i915, meta);
set_vertex_format(intel);
meta_no_texture(intel);
}
void
i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
static void leave_meta_state( struct intel_context *intel )
{
i915ContextPtr i915 = I915_CONTEXT( intel );
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelScreenPrivate *screen = intel->intelScreen;
int x0, y0, x1, y1;
SET_STATE( i915, meta );
set_initial_state( i915 );
set_no_texture( i915 );
set_vertex_format( i915 );
LOCK_HARDWARE(intel);
if(!all) {
x0 = cx;
y0 = cy;
x1 = x0 + cw;
y1 = y0 + ch;
} else {
x0 = 0;
y0 = 0;
x1 = x0 + dPriv->w;
y1 = y0 + dPriv->h;
}
/* Don't do any clipping to screen - these are window coordinates.
* The active cliprects will be applied as for any other geometry.
*/
if (mask & BUFFER_BIT_FRONT_LEFT) {
set_no_depth_stencil_write( i915 );
set_color_mask( i915, GL_TRUE );
set_draw_offset( i915, screen->front.offset );
draw_quad(i915, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if (mask & BUFFER_BIT_BACK_LEFT) {
set_no_depth_stencil_write( i915 );
set_color_mask( i915, GL_TRUE );
set_draw_offset( i915, screen->back.offset );
draw_quad(i915, x0, x1, y0, y1,
intel->clear_red, intel->clear_green,
intel->clear_blue, intel->clear_alpha,
0, 0, 0, 0);
}
if (mask & BUFFER_BIT_STENCIL) {
set_stencil_replace( i915,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
set_color_mask( i915, GL_FALSE );
set_draw_offset( i915, screen->front.offset ); /* could be either? */
draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
}
UNLOCK_HARDWARE(intel);
SET_STATE( i915, state );
struct i915_context *i915 = i915_context(&intel->ctx);
intel_region_release(intel, &i915->meta.draw_region);
intel_region_release(intel, &i915->meta.depth_region);
intel_region_release(intel, &i915->meta.tex_region[0]);
SET_STATE(i915, state);
}
void i915InitMetaFuncs( struct i915_context *i915 )
{
i915->intel.vtbl.install_meta_state = install_meta_state;
i915->intel.vtbl.leave_meta_state = leave_meta_state;
i915->intel.vtbl.meta_no_depth_stencil_write = meta_no_depth_stencil_write;
i915->intel.vtbl.meta_stencil_replace = meta_stencil_replace;
i915->intel.vtbl.meta_color_mask = meta_color_mask;
i915->intel.vtbl.meta_no_texture = meta_no_texture;
i915->intel.vtbl.meta_texture_blend_replace = meta_texture_blend_replace;
i915->intel.vtbl.meta_tex_rect_source = meta_tex_rect_source;
i915->intel.vtbl.meta_draw_region = meta_draw_region;
i915->intel.vtbl.meta_draw_format = set_draw_format;
}

View File

@@ -358,7 +358,7 @@ void i915_program_error( struct i915_fragment_program *p, const char *msg )
p->error = 1;
}
void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p )
void i915_init_program( struct i915_context *i915, struct i915_fragment_program *p )
{
GLcontext *ctx = &i915->intel.ctx;
TNLcontext *tnl = TNL_CONTEXT( ctx );
@@ -431,7 +431,7 @@ void i915_fini_program( struct i915_fragment_program *p )
p->declarations[0] |= program_size + decl_size - 2;
}
void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p )
void i915_upload_program( struct i915_context *i915, struct i915_fragment_program *p )
{
GLuint program_size = p->csr - p->program;
GLuint decl_size = p->decl - p->declarations;

View File

@@ -84,7 +84,7 @@
/* One neat thing about the UREG representation:
*/
static __inline int swizzle( int reg, int x, int y, int z, int w )
static inline int swizzle( int reg, int x, int y, int z, int w )
{
return ((reg & ~UREG_XYZW_CHANNEL_MASK) |
CHANNEL_SRC( GET_CHANNEL_SRC( reg, x ), 0 ) |
@@ -95,7 +95,7 @@ static __inline int swizzle( int reg, int x, int y, int z, int w )
/* Another neat thing about the UREG representation:
*/
static __inline int negate( int reg, int x, int y, int z, int w )
static inline int negate( int reg, int x, int y, int z, int w )
{
return reg ^ (((x&1)<<UREG_CHANNEL_X_NEGATE_SHIFT)|
((y&1)<<UREG_CHANNEL_Y_NEGATE_SHIFT)|
@@ -149,10 +149,10 @@ extern GLuint i915_emit_param4fv( struct i915_fragment_program *p,
extern void i915_program_error( struct i915_fragment_program *p,
const char *msg );
extern void i915_init_program( i915ContextPtr i915,
extern void i915_init_program( struct i915_context *i915,
struct i915_fragment_program *p );
extern void i915_upload_program( i915ContextPtr i915,
extern void i915_upload_program( struct i915_context *i915,
struct i915_fragment_program *p );
extern void i915_fini_program( struct i915_fragment_program *p );

View File

@@ -435,10 +435,10 @@
#define LOGICOP_MASK (0xf<<18)
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
#define ENABLE_STENCIL_TEST_MASK (1<<17)
#define STENCIL_TEST_MASK(x) ((x)<<8)
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8)
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
#define STENCIL_WRITE_MASK(x) (x)
#define STENCIL_WRITE_MASK(x) ((x)&0xff)
/* _3DSTATE_MODES_5, p220 */
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))

View File

@@ -48,7 +48,7 @@ static void
i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
GLuint mask)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int test = intel_translate_compare_func( func );
mask = mask & 0xff;
@@ -73,7 +73,7 @@ i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
static void
i915StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
if (INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask);
@@ -91,7 +91,7 @@ static void
i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
GLenum zpass)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int fop = intel_translate_stencil_op(fail);
int dfop = intel_translate_stencil_op(zfail);
int dpop = intel_translate_stencil_op(zpass);
@@ -116,7 +116,7 @@ i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int test = intel_translate_compare_func( func );
GLubyte refByte;
@@ -137,7 +137,7 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
*/
static void i915EvalLogicOpBlendState(GLcontext *ctx)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
@@ -157,7 +157,7 @@ static void i915EvalLogicOpBlendState(GLcontext *ctx)
static void i915BlendColor(GLcontext *ctx, const GLfloat color[4])
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLubyte r, g, b, a;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -194,7 +194,7 @@ static GLuint translate_blend_equation( GLenum mode )
static void i915UpdateBlendState( GLcontext *ctx )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &
~(IAB_SRC_FACTOR_MASK |
IAB_DST_FACTOR_MASK |
@@ -261,7 +261,7 @@ static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB,
static void i915DepthFunc(GLcontext *ctx, GLenum func)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int test = intel_translate_compare_func( func );
if (INTEL_DEBUG&DEBUG_DRI)
@@ -274,7 +274,7 @@ static void i915DepthFunc(GLcontext *ctx, GLenum func)
static void i915DepthMask(GLcontext *ctx, GLboolean flag)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
if (INTEL_DEBUG&DEBUG_DRI)
fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag);
@@ -295,7 +295,7 @@ static void i915DepthMask(GLcontext *ctx, GLboolean flag)
*/
static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
const GLubyte *m = mask;
GLubyte p[4];
int i,j,k;
@@ -348,7 +348,7 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
GLsizei w, GLsizei h)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
intelScreenPrivate *screen = i915->intel.intelScreen;
int x1, y1, x2, y2;
@@ -382,7 +382,7 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
static void i915LogicOp(GLcontext *ctx, GLenum opcode)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int tmp = intel_translate_logic_op(opcode);
if (INTEL_DEBUG&DEBUG_DRI)
@@ -397,7 +397,7 @@ static void i915LogicOp(GLcontext *ctx, GLenum opcode)
static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLuint mode;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -425,7 +425,7 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
{
i915ContextPtr i915 = I915_CONTEXT( ctx );
struct i915_context *i915 = I915_CONTEXT( ctx );
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK;
int width;
@@ -444,7 +444,7 @@ static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
static void i915PointSize(GLcontext *ctx, GLfloat size)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK;
GLint point_size = (int)size;
@@ -469,7 +469,7 @@ static void i915ColorMask(GLcontext *ctx,
GLboolean r, GLboolean g,
GLboolean b, GLboolean a)
{
i915ContextPtr i915 = I915_CONTEXT( ctx );
struct i915_context *i915 = I915_CONTEXT( ctx );
GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK;
if (INTEL_DEBUG&DEBUG_DRI)
@@ -490,7 +490,7 @@ static void update_specular( GLcontext *ctx )
{
/* A hack to trigger the rebuild of the fragment program.
*/
INTEL_CONTEXT(ctx)->NewGLState |= _NEW_TEXTURE;
intel_context(ctx)->NewGLState |= _NEW_TEXTURE;
I915_CONTEXT(ctx)->tex_program.translated = 0;
}
@@ -507,7 +507,7 @@ static void i915LightModelfv(GLcontext *ctx, GLenum pname,
static void i915ShadeModel(GLcontext *ctx, GLenum mode)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
if (mode == GL_SMOOTH) {
@@ -526,7 +526,7 @@ static void i915ShadeModel(GLcontext *ctx, GLenum mode)
*/
void i915_update_fog( GLcontext *ctx )
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
GLenum mode;
GLboolean enabled;
GLboolean try_pixel_fog;
@@ -619,7 +619,7 @@ void i915_update_fog( GLcontext *ctx )
static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
switch (pname) {
case GL_FOG_COORDINATE_SOURCE_EXT:
@@ -671,7 +671,7 @@ static void i915Hint(GLcontext *ctx, GLenum target, GLenum state)
static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
{
i915ContextPtr i915 = I915_CONTEXT(ctx);
struct i915_context *i915 = I915_CONTEXT(ctx);
switch(cap) {
case GL_TEXTURE_2D:
@@ -785,7 +785,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
}
static void i915_init_packets( i915ContextPtr i915 )
static void i915_init_packets( struct i915_context *i915 )
{
intelScreenPrivate *screen = i915->intel.intelScreen;
@@ -823,7 +823,6 @@ static void i915_init_packets( i915ContextPtr i915 )
ENABLE_STENCIL_WRITE_MASK |
STENCIL_WRITE_MASK(0xff));
i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
IAB_MODIFY_ENABLE |
IAB_MODIFY_FUNC |
@@ -862,19 +861,15 @@ static void i915_init_packets( i915ContextPtr i915 )
BUF_3D_PITCH(screen->front.pitch * screen->cpp) |
BUF_3D_USE_FENCE);
i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
i915->state.Buffer[I915_DESTREG_DBUFADDR1] =
(BUF_3D_ID_DEPTH |
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) |
BUF_3D_USE_FENCE);
i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset;
i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
switch (screen->fbFormat) {
case DV_PF_555:
case DV_PF_565:
i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
DSTORG_VERT_BIAS(0x8) | /* .5 */
@@ -905,9 +900,10 @@ static void i915_init_packets( i915ContextPtr i915 )
* we get hardware contexts working.
*/
i915->state.active = (I915_UPLOAD_PROGRAM |
I915_UPLOAD_STIPPLE |
I915_UPLOAD_CTX |
I915_UPLOAD_BUFFERS);
I915_UPLOAD_STIPPLE |
I915_UPLOAD_CTX |
I915_UPLOAD_BUFFERS |
I915_UPLOAD_INVARIENT);
}
void i915InitStateFunctions( struct dd_function_table *functions )
@@ -937,7 +933,7 @@ void i915InitStateFunctions( struct dd_function_table *functions )
}
void i915InitState( i915ContextPtr i915 )
void i915InitState( struct i915_context *i915 )
{
GLcontext *ctx = &i915->intel.ctx;

View File

@@ -45,76 +45,10 @@
/**
* Allocate space for and load the mesa images into the texture memory block.
* This will happen before drawing with a new texture, or drawing with a
* texture after it was swapped out or teximaged again.
*/
intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj )
{
i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object );
if ( !t )
return NULL;
texObj->DriverData = t;
t->intel.base.tObj = texObj;
t->intel.dirty = I915_UPLOAD_TEX_ALL;
make_empty_list( &t->intel.base );
return &t->intel;
}
static void i915TexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_WRAP_R:
case GL_TEXTURE_BORDER_COLOR:
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
case GL_TEXTURE_COMPARE_MODE:
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
case GL_TEXTURE_COMPARE_FUNC:
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* The i915 and its successors can do a lot of this without
* reloading the textures. A project for someone?
*/
intelFlush( ctx );
driSwapOutTextureObject( (driTextureObject *) t );
t->intel.dirty = I915_UPLOAD_TEX_ALL;
break;
default:
return;
}
}
static void i915TexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
i915ContextPtr i915 = I915_CONTEXT( ctx );
GLuint unit = ctx->Texture.CurrentUnit;
struct i915_context *i915 = I915_CONTEXT( ctx );
switch (pname) {
case GL_TEXTURE_ENV_COLOR: /* Should be a tracked param */
@@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
break;
case GL_TEXTURE_LOD_BIAS: {
int b = (int) ((*param) * 16.0);
GLuint unit = ctx->Texture.CurrentUnit;
GLint b = (int) ((*param) * 16.0);
if (b > 255) b = 255;
if (b < -256) b = -256;
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK;
i915->state.Tex[unit][I915_TEXREG_SS2] |=
((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
break;
}
@@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
static void i915BindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj )
struct gl_texture_object *texobj )
{
i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData;
if (tex->lastTarget != texObj->Target) {
tex->intel.dirty = I915_UPLOAD_TEX_ALL;
tex->lastTarget = texObj->Target;
}
/* Need this if image format changes between bound textures.
* Could try and shortcircuit by checking for differences in
* state between incoming and outgoing textures:
@@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions )
{
functions->BindTexture = i915BindTexture;
functions->TexEnv = i915TexEnv;
functions->TexParameter = i915TexParameter;
}

View File

@@ -0,0 +1,333 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
/* Code to layout images in a mipmap tree for i915 and i945
* respectively.
*/
#include "intel_mipmap_tree.h"
#include "macros.h"
static GLint initial_offsets[6][2] = { {0,0},
{0,2},
{1,0},
{1,2},
{1,1},
{1,3} };
static GLint step_offsets[6][2] = { {0,2},
{0,2},
{-1,2},
{-1,2},
{-1,1},
{-1,1} };
static GLuint minify( GLuint d )
{
return MAX2(1, d>>1);
}
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
{
GLint i;
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP: {
const GLuint dim = mt->width0;
GLuint face;
/* double pitch for cube layouts */
mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
mt->total_height = dim * 4;
for ( face = 0 ; face < 6 ; face++) {
GLuint x = initial_offsets[face][0] * dim;
GLuint y = initial_offsets[face][1] * dim;
GLuint d = dim;
for (i = mt->first_level; i <= mt->last_level; i++) {
intel_miptree_set_image_offset(mt, face, i,
x, y,
d, d, 1);
if (d == 0)
_mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
face, i, mt->first_level, mt->last_level);
d >>= 1;
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
}
}
break;
}
case GL_TEXTURE_3D: {
GLuint width = mt->width0;
GLuint height = mt->height0;
GLuint depth = mt->depth0;
/* Calculate the size of a single slice.
*/
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
/* XXX: hardware expects/requires 9 levels at minimum.
*/
for ( i = mt->first_level ; i <= MAX2(8, mt->last_level) ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
0, mt->total_height,
width, height, depth);
mt->total_height += MAX2(2, height);
width = minify(width);
height = minify(height);
depth = minify(depth);
}
/* Fixup depth_image_stride:
*/
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
mt->offset[0][i].depth_image_stride = mt->total_height * mt->pitch * mt->cpp;
}
/* Multiply slice size by texture depth for total size. It's
* remarkable how wasteful of memory the i915 texture layouts
* are. They are largely fixed in the i945.
*/
mt->total_height *= mt->depth0;
break;
}
default: {
GLuint width = mt->width0;
GLuint height = mt->height0;
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
0, mt->total_height,
width, height, 1);
if (mt->compressed)
mt->total_height += MAX2(1, height/4);
else
mt->total_height += MAX2(2, height);
width = minify(width);
height = minify(height);
}
break;
}
}
DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
mt->pitch,
mt->total_height,
mt->cpp,
mt->pitch * mt->total_height * mt->cpp );
return GL_TRUE;
}
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
{
GLint i;
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP: {
const GLuint dim = mt->width0;
GLuint face;
/* Depending on the size of the largest images, pitch can be
* determined either by the old-style packing of cubemap faces,
* or the final row of 4x4, 2x2 and 1x1 faces below this.
*/
if (dim > 32)
mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
else
mt->pitch = 14 * 8;
mt->total_height = dim * 4 + 4;
for ( face = 0 ; face < 6 ; face++) {
GLuint x = initial_offsets[face][0] * dim;
GLuint y = initial_offsets[face][1] * dim;
GLuint d = dim;
if (dim == 4 && face >= 4) {
y = mt->total_height - 4;
x = (face - 4) * 8;
}
else if (dim < 4) {
y = mt->total_height - 4;
x = face * 8;
}
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, face, i,
x, y,
d, d, 1);
d >>= 1;
switch (d) {
case 4:
switch (face) {
case FACE_POS_X:
case FACE_NEG_X:
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
break;
case FACE_POS_Y:
case FACE_NEG_Y:
y += 12;
x -= 8;
break;
case FACE_POS_Z:
case FACE_NEG_Z:
y = mt->total_height - 4;
x = (face - 4) * 8;
break;
}
case 2:
y = mt->total_height - 4;
x = 16 + face * 8;
break;
case 1:
x += 48;
break;
default:
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
break;
}
}
}
break;
}
case GL_TEXTURE_3D: {
GLuint width = mt->width0;
GLuint height = mt->height0;
GLuint depth = mt->depth0;
GLuint depth_pack_pitch;
GLuint depth_packing = 0;
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
depth_pack_pitch = mt->pitch * mt->cpp;
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
0, mt->total_height,
width, height, depth);
mt->total_height += MAX2(2, height) * MAX2((depth >> depth_packing), 1);
/* When alignment dominates, can't increase depth packing?
* Or does pitch grow??? What are the alignment constraints,
* anyway?
*/
if (depth_pack_pitch > 4) {
depth_packing++;
depth_pack_pitch >>= 2; /* KW: is this right?? */
}
width = minify(width);
height = minify(height);
depth = minify(depth);
/* XXX: Not sure how 3d textures work on i945 - where did
* t->depth_pitch get set in the old code. Did it ever work?
* Fix up later.
*/
}
break;
}
default: {
GLuint x = 0;
GLuint y = 0;
GLuint width = mt->width0;
GLuint height = mt->height0;
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
intel_miptree_set_image_offset(mt, 0, i,
x, y,
width, height, 1);
/* LPT change: step right after second mipmap.
*/
if (i == 1)
x += mt->pitch / 2;
else {
GLuint img_height;
if (mt->compressed)
img_height = MAX2(1, height/4);
else
img_height = MAX2(2, height);
y += img_height;
}
/* Because the images are packed better, the final offset
* might not be the maximal one:
*/
mt->total_height = MAX2(mt->total_height, y);
width = minify(width);
height = minify(height);
}
break;
}
}
DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
mt->pitch,
mt->total_height,
mt->cpp,
mt->pitch * mt->total_height * mt->cpp );
return GL_TRUE;
}

View File

@@ -536,7 +536,7 @@ static void emit_program_fini( struct i915_fragment_program *p )
}
static void i915EmitTextureProgram( i915ContextPtr i915 )
static void i915EmitTextureProgram( struct i915_context *i915 )
{
GLcontext *ctx = &i915->intel.ctx;
struct i915_fragment_program *p = &i915->tex_program;
@@ -570,9 +570,9 @@ static void i915EmitTextureProgram( i915ContextPtr i915 )
}
void i915ValidateTextureProgram( i915ContextPtr i915 )
void i915ValidateTextureProgram( struct i915_context *i915 )
{
intelContextPtr intel = &i915->intel;
struct intel_context *intel = &i915->intel;
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;

File diff suppressed because it is too large Load Diff

View File

@@ -37,14 +37,16 @@
#include "tnl/t_vertex.h"
#include "intel_batchbuffer.h"
#include "intel_tex.h"
#include "intel_regions.h"
#include "i915_reg.h"
#include "i915_context.h"
static void i915_render_start( intelContextPtr intel )
static void i915_render_start( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
if (ctx->FragmentProgram._Active)
i915ValidateFragmentProgram( i915 );
@@ -53,42 +55,42 @@ static void i915_render_start( intelContextPtr intel )
}
static void i915_reduced_primitive_state( intelContextPtr intel,
static void i915_reduced_primitive_state( struct intel_context *intel,
GLenum rprim )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
struct i915_context *i915 = i915_context(&intel->ctx);
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
st1 &= ~ST1_ENABLE;
st1 &= ~ST1_ENABLE;
switch (rprim) {
case GL_TRIANGLES:
if (intel->ctx.Polygon.StippleFlag &&
intel->hw_stipple)
st1 |= ST1_ENABLE;
break;
case GL_LINES:
case GL_POINTS:
default:
break;
}
switch (rprim) {
case GL_TRIANGLES:
if (intel->ctx.Polygon.StippleFlag &&
intel->hw_stipple)
st1 |= ST1_ENABLE;
break;
case GL_LINES:
case GL_POINTS:
default:
break;
}
i915->intel.reduced_primitive = rprim;
i915->intel.reduced_primitive = rprim;
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
i915->state.Stipple[I915_STPREG_ST1] = st1;
}
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
i915->state.Stipple[I915_STPREG_ST1] = st1;
}
}
/* Pull apart the vertex format registers and figure out how large a
* vertex is supposed to be.
*/
static GLboolean i915_check_vertex_size( intelContextPtr intel,
static GLboolean i915_check_vertex_size( struct intel_context *intel,
GLuint expected )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
int lis2 = i915->current->Ctx[I915_CTXREG_LIS2];
int lis4 = i915->current->Ctx[I915_CTXREG_LIS4];
int i, sz = 0;
@@ -132,11 +134,11 @@ static GLboolean i915_check_vertex_size( intelContextPtr intel,
}
static void i915_emit_invarient_state( intelContextPtr intel )
static void i915_emit_invarient_state( struct intel_context *intel )
{
BATCH_LOCALS;
BEGIN_BATCH( 200 );
BEGIN_BATCH( 200, 0 );
OUT_BATCH(_3DSTATE_AA_CMD |
AA_LINE_ECAAR_WIDTH_ENABLE |
@@ -204,21 +206,15 @@ static void i915_emit_invarient_state( intelContextPtr intel )
}
#define emit( intel, state, size ) \
do { \
int k; \
BEGIN_BATCH( (size) / sizeof(GLuint)); \
for (k = 0 ; k < (size) / sizeof(GLuint) ; k++) \
OUT_BATCH((state)[k]); \
ADVANCE_BATCH(); \
} while (0);
#define emit(intel, state, size ) \
intel_batchbuffer_data(intel->batch, state, size, 0 )
/* Push the state into the sarea and/or texture memory.
*/
static void i915_emit_state( intelContextPtr intel )
static void i915_emit_state( struct intel_context *intel )
{
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
struct i915_hw_state *state = i915->current;
int i;
GLuint dirty;
@@ -233,27 +229,48 @@ static void i915_emit_state( intelContextPtr intel )
dirty = state->active & ~state->emitted;
if (VERBOSE)
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
if (dirty & I915_UPLOAD_INVARIENT) {
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n");
i915_emit_invarient_state( intel );
}
if (dirty & I915_UPLOAD_CTX) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");
emit( i915, state->Ctx, sizeof(state->Ctx) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n");
emit(intel, state->Ctx, sizeof(state->Ctx) );
}
if (dirty & I915_UPLOAD_BUFFERS) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
emit( i915, state->Buffer, sizeof(state->Buffer) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
BEGIN_BATCH(I915_DEST_SETUP_SIZE, 0);
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]);
OUT_RELOC(state->draw_region->buffer, BM_MEM_AGP|BM_WRITE, 0);
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]);
OUT_RELOC(state->depth_region->buffer, BM_MEM_AGP|BM_WRITE, 0);
OUT_BATCH(state->Buffer[I915_DESTREG_DV0]);
OUT_BATCH(state->Buffer[I915_DESTREG_DV1]);
OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]);
OUT_BATCH(state->Buffer[I915_DESTREG_SR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_SR1]);
OUT_BATCH(state->Buffer[I915_DESTREG_SR2]);
ADVANCE_BATCH();
}
if (dirty & I915_UPLOAD_STIPPLE) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
emit( i915, state->Stipple, sizeof(state->Stipple) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
emit(intel, state->Stipple, sizeof(state->Stipple) );
}
if (dirty & I915_UPLOAD_FOG) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n");
emit( i915, state->Fog, sizeof(state->Fog) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_FOG:\n");
emit(intel, state->Fog, sizeof(state->Fog) );
}
/* Combine all the dirty texture state into a single command to
@@ -266,18 +283,29 @@ static void i915_emit_state( intelContextPtr intel )
if (dirty & I915_UPLOAD_TEX(i))
nr++;
BEGIN_BATCH(2+nr*3);
BEGIN_BATCH(2+nr*3, 0);
OUT_BATCH(_3DSTATE_MAP_STATE | (3*nr));
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
for (i = 0 ; i < I915_TEX_UNITS ; i++)
if (dirty & I915_UPLOAD_TEX(i)) {
OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]);
if (state->tex_region[i]) {
OUT_RELOC(state->tex_region[i]->buffer,
BM_MEM_AGP|BM_READ,
state->tex_offset[i]);
}
else {
assert(i == 0);
assert(state == &i915->meta);
OUT_BATCH(0);
}
OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]);
OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]);
}
ADVANCE_BATCH();
BEGIN_BATCH(2+nr*3);
BEGIN_BATCH(2+nr*3, 0);
OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3*nr));
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
for (i = 0 ; i < I915_TEX_UNITS ; i++)
@@ -290,64 +318,65 @@ static void i915_emit_state( intelContextPtr intel )
}
if (dirty & I915_UPLOAD_CONSTANTS) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) );
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint) );
}
if (dirty & I915_UPLOAD_PROGRAM) {
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
assert((state->Program[0] & 0x1ff)+2 == state->ProgramSize);
emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) );
if (VERBOSE)
emit(intel, state->Program, state->ProgramSize * sizeof(GLuint) );
if (INTEL_DEBUG & DEBUG_STATE)
i915_disassemble_program( state->Program, state->ProgramSize );
}
state->emitted |= dirty;
}
static void i915_destroy_context( intelContextPtr intel )
static void i915_destroy_context( struct intel_context *intel )
{
_tnl_free_vertices(&intel->ctx);
}
static void i915_set_draw_offset( intelContextPtr intel, int offset )
static void i915_set_draw_region( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region)
{
i915ContextPtr i915 = I915_CONTEXT(intel);
struct i915_context *i915 = i915_context(&intel->ctx);
intel_region_release(intel, &i915->state.draw_region);
intel_region_release(intel, &i915->state.depth_region);
intel_region_reference(&i915->state.draw_region, draw_region);
intel_region_reference(&i915->state.depth_region, depth_region);
I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS );
i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset;
}
static void i915_lost_hardware( intelContextPtr intel )
static void i915_lost_hardware( struct intel_context *intel )
{
I915_CONTEXT(intel)->state.emitted = 0;
struct i915_context *i915 = i915_context(&intel->ctx);
i915->state.emitted = 0;
}
static void i915_emit_flush( intelContextPtr intel )
static GLuint i915_flush_cmd( void )
{
BATCH_LOCALS;
BEGIN_BATCH(2);
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE );
OUT_BATCH( 0 );
ADVANCE_BATCH();
return MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE;
}
void i915InitVtbl( i915ContextPtr i915 )
void i915InitVtbl( struct i915_context *i915 )
{
i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj;
i915->intel.vtbl.check_vertex_size = i915_check_vertex_size;
i915->intel.vtbl.clear_with_tris = i915ClearWithTris;
i915->intel.vtbl.destroy = i915_destroy_context;
i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state;
i915->intel.vtbl.emit_state = i915_emit_state;
i915->intel.vtbl.lost_hardware = i915_lost_hardware;
i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state;
i915->intel.vtbl.render_start = i915_render_start;
i915->intel.vtbl.set_draw_offset = i915_set_draw_offset;
i915->intel.vtbl.set_draw_region = i915_set_draw_region;
i915->intel.vtbl.update_texture_state = i915UpdateTextureState;
i915->intel.vtbl.emit_flush = i915_emit_flush;
i915->intel.vtbl.flush_cmd = i915_flush_cmd;
}

View File

@@ -1,6 +1,6 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,664 +25,266 @@
*
**************************************************************************/
#include <stdio.h>
#include <errno.h>
#include "mtypes.h"
#include "context.h"
#include "enums.h"
#include "intel_reg.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "bufmgr.h"
/* ================================================================
* Performance monitoring functions
/* Relocations in kernel space:
* - pass dma buffer seperately
* - memory manager knows how to patch
* - pass list of dependent buffers
* - pass relocation list
*
* Either:
* - get back an offset for buffer to fire
* - memory manager knows how to fire buffer
*
* Really want the buffer to be AGP and pinned.
*
*/
static void intel_fill_box( intelContextPtr intel,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLubyte r, GLubyte g, GLubyte b )
/* Cliprect fence: The highest fence protecting a dma buffer
* containing explicit cliprect information. Like the old drawable
* lock but irq-driven. X server must wait for this fence to expire
* before changing cliprects [and then doing sw rendering?]. For
* other dma buffers, the scheduler will grab current cliprect info
* and mix into buffer. X server must hold the lock while changing
* cliprects??? Make per-drawable. Need cliprects in shared memory
* -- beats storing them with every cmd buffer in the queue.
*
* ==> X server must wait for this fence to expire before touching the
* framebuffer with new cliprects.
*
* ==> Cliprect-dependent buffers associated with a
* cliprect-timestamp. All of the buffers associated with a timestamp
* must go to hardware before any buffer with a newer timestamp.
*
* ==> Dma should be queued per-drawable for correct X/GL
* synchronization. Or can fences be used for this?
*
* Applies to: Blit operations, metaops, X server operations -- X
* server automatically waits on its own dma to complete before
* modifying cliprects ???
*/
static void intel_dump_batchbuffer( unsigned offset,
int *ptr,
int count )
{
intelEmitFillBlitLocked( intel,
intel->intelScreen->cpp,
intel->intelScreen->back.pitch,
intel->intelScreen->front.offset,
x, y, w, h,
INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
r,g,b,0xff));
}
static void intel_draw_performance_boxes( intelContextPtr intel )
{
/* Purple box for page flipping
*/
if ( intel->perf_boxes & I830_BOX_FLIP )
intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
/* Red box if we have to wait for idle at any point
*/
if ( intel->perf_boxes & I830_BOX_WAIT )
intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
/* Blue box: lost context?
*/
if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )
intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
/* Yellow box for texture swaps
*/
if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )
intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
/* Green box if hardware never idles (as far as we can tell)
*/
if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )
intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
/* Draw bars indicating number of buffers allocated
* (not a great measure, easily confused)
*/
#if 0
if (intel->dma_used) {
int bar = intel->dma_used / 10240;
if (bar > 100) bar = 100;
if (bar < 1) bar = 1;
intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
intel->dma_used = 0;
}
#endif
intel->perf_boxes = 0;
int i;
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count/4);
for (i = 0; i < count/4; i += 4)
fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",
offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]);
fprintf(stderr, "END BATCH\n\n\n");
}
static int bad_prim_vertex_nr( int primitive, int nr )
static void intel_batchbuffer_reset( struct intel_batchbuffer *batch )
{
switch (primitive & PRIM3D_MASK) {
case PRIM3D_POINTLIST:
return nr < 1;
case PRIM3D_LINELIST:
return (nr & 1) || nr == 0;
case PRIM3D_LINESTRIP:
return nr < 2;
case PRIM3D_TRILIST:
case PRIM3D_RECTLIST:
return nr % 3 || nr == 0;
case PRIM3D_POLY:
case PRIM3D_TRIFAN:
case PRIM3D_TRISTRIP:
case PRIM3D_TRISTRIP_RVRSE:
return nr < 3;
default:
return 1;
}
bmBufferData(batch->bm,
batch->buffer,
BATCH_SZ,
NULL,
0);
if (!batch->list)
batch->list = bmNewBufferList();
batch->list->nr = 0;
batch->nr_relocs = 0;
batch->flags = 0;
bmAddBuffer( batch->list,
batch->buffer,
0,
NULL,
&batch->offset[batch->list->nr]);
batch->map = bmMapBuffer(batch->bm, batch->buffer,
BM_MEM_AGP|BM_MEM_LOCAL|BM_CLIENT|BM_WRITE);
batch->ptr = batch->map;
}
static void intel_flush_inline_primitive( GLcontext *ctx )
/*======================================================================
* Public functions
*/
struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
GLuint used = intel->batch.ptr - intel->prim.start_ptr;
GLuint vertcount;
struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
assert(intel->prim.primitive != ~0);
batch->intel = intel;
batch->bm = intel->bm;
if (1) {
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))
goto do_discard;
bmGenBuffers(intel->bm, 1, &batch->buffer);
intel_batchbuffer_reset( batch );
return batch;
}
vertcount = (used - 4)/ (intel->vertex_size * 4);
if (!vertcount)
goto do_discard;
if (vertcount * intel->vertex_size * 4 != used - 4) {
fprintf(stderr, "vertex size confusion %d %d\n", used,
intel->vertex_size * vertcount * 4);
goto do_discard;
}
if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
vertcount);
goto do_discard;
}
}
if (used < 8)
goto do_discard;
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
intel->prim.primitive |
(used/4-2));
goto finished;
void intel_batchbuffer_free( struct intel_batchbuffer *batch )
{
if (batch->map)
bmUnmapBuffer(batch->bm, batch->buffer);
do_discard:
intel->batch.ptr -= used;
intel->batch.space += used;
assert(intel->batch.space >= 0);
finished:
intel->prim.primitive = ~0;
intel->prim.start_ptr = 0;
intel->prim.flush = 0;
free(batch);
}
/* Emit a primitive referencing vertices in a vertex buffer.
/* TODO: Push this whole function into bufmgr.
*/
void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
static void do_flush_locked( struct intel_batchbuffer *batch,
GLuint used,
GLboolean ignore_cliprects)
{
BATCH_LOCALS;
GLuint *ptr;
GLuint i;
if (0)
fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
bmValidateBufferList( batch->bm,
batch->list,
BM_MEM_AGP );
/* Finish any in-progress primitive:
/* Apply the relocations. This nasty map indicates to me that the
* whole task should be done internally by the memory manager, and
* that dma buffers probably need to be pinned within agp space.
*/
INTEL_FIREVERTICES( intel );
ptr = (GLuint *)bmMapBuffer(batch->bm, batch->buffer,
BM_NO_MOVE|BM_NO_UPLOAD|
BM_NO_EVICT|BM_MEM_AGP|
BM_WRITE);
for (i = 0; i < batch->nr_relocs; i++) {
struct buffer_reloc *r = &batch->reloc[i];
DBG("apply fixup at offset 0x%x, elem %d (buf %d, offset 0x%x), delta 0x%x\n",
r->offset, r->elem, batch->list->elem[r->elem].buffer,
batch->offset[r->elem], r->delta);
ptr[r->offset/4] = batch->offset[r->elem] + r->delta;
}
if (INTEL_DEBUG & DEBUG_DMA)
intel_dump_batchbuffer( 0, ptr, used );
bmUnmapBuffer(batch->bm, batch->buffer);
/* Fire the batch buffer, which was uploaded above:
*/
intel_batch_ioctl(batch->intel,
batch->offset[0],
used,
ignore_cliprects);
/* Emit outstanding state:
batch->last_fence = bmFenceBufferList(batch->bm, batch->list);
}
GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch )
{
struct intel_context *intel = batch->intel;
GLuint used = batch->ptr - batch->map;
if (used == 0)
return batch->last_fence;
/* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
* performance drain that we would like to avoid.
*/
intel->vtbl.emit_state( intel );
/* Make sure there is some space in this buffer:
*/
if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space)
intelFlushBatch(intel, GL_TRUE);
#if 1
if (((int)intel->batch.ptr) & 0x4) {
BEGIN_BATCH(1);
OUT_BATCH(0);
ADVANCE_BATCH();
}
#endif
/* Emit a slot which will be filled with the inline primitive
* command later.
*/
BEGIN_BATCH(2);
OUT_BATCH( 0 );
intel->prim.start_ptr = batch_ptr;
intel->prim.primitive = prim;
intel->prim.flush = intel_flush_inline_primitive;
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void intelRestartInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
intel_flush_inline_primitive( &intel->ctx );
if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
intelStartInlinePrimitive( intel, prim );
}
void intelWrapInlinePrimitive( intelContextPtr intel )
{
GLuint prim = intel->prim.primitive;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
intel_flush_inline_primitive( &intel->ctx );
intelFlushBatch(intel, GL_TRUE);
intelStartInlinePrimitive( intel, prim );
}
/* Emit a primitive with space for inline vertices.
*/
GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive,
int dwords,
int vertex_size )
{
GLuint *tmp = 0;
BATCH_LOCALS;
if (0)
fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
/* Emit outstanding state:
*/
intel->vtbl.emit_state( intel );
if (1) {
int used = dwords * 4;
int vertcount;
/* Check vertex size against the vertex we're specifying to
* hardware. If it's wrong, ditch the primitive.
*/
if (!intel->vtbl.check_vertex_size( intel, vertex_size ))
goto do_discard;
vertcount = dwords / vertex_size;
if (dwords % vertex_size) {
fprintf(stderr, "did not request a whole number of vertices\n");
goto do_discard;
}
if (bad_prim_vertex_nr( primitive, vertcount )) {
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
goto do_discard;
}
if (used < 8)
goto do_discard;
}
/* Emit 3D_PRIMITIVE commands:
*/
BEGIN_BATCH(1 + dwords);
OUT_BATCH( _3DPRIMITIVE |
primitive |
(dwords-1) );
tmp = (GLuint *)batch_ptr;
batch_ptr += dwords * 4;
ADVANCE_BATCH();
do_discard:
return tmp;
}
/*
* Copy the back buffer to the front buffer.
*/
void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
{
intelContextPtr intel;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
intelScreenPrivate *intelScreen = intel->intelScreen;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *pbox = dPriv->pClipRects;
int pitch = intelScreen->front.pitch;
int cpp = intelScreen->cpp;
int i;
GLuint CMD, BR13;
BATCH_LOCALS;
switch(cpp) {
case 2:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
}
if (0)
intel_draw_performance_boxes( intel );
for (i = 0 ; i < nbox; i++, pbox++)
{
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
pbox->x2 > intelScreen->width ||
pbox->y2 > intelScreen->height)
continue;
BEGIN_BATCH( 8);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
if (intel->sarea->pf_current_page == 0)
OUT_BATCH( intelScreen->front.offset );
else
OUT_BATCH( intelScreen->back.offset );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( BR13 & 0xffff );
if (intel->sarea->pf_current_page == 0)
OUT_BATCH( intelScreen->back.offset );
else
OUT_BATCH( intelScreen->front.offset );
ADVANCE_BATCH();
}
}
intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
void intelEmitFillBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color )
{
GLuint BR13, CMD;
BATCH_LOCALS;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
break;
default:
return;
}
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (y << 16) | x );
OUT_BATCH( ((y+h) << 16) | (x+w) );
OUT_BATCH( dst_offset );
OUT_BATCH( color );
ADVANCE_BATCH();
}
/* Copy BitBlt
*/
void intelEmitCopyBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_offset,
GLshort src_x, GLshort src_y,
GLshort dst_x, GLshort dst_y,
GLshort w, GLshort h )
{
GLuint CMD, BR13;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
BATCH_LOCALS;
src_pitch *= cpp;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
return;
}
if (dst_y2 < dst_y ||
dst_x2 < dst_x) {
return;
}
BEGIN_BATCH( 12);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (dst_y << 16) | dst_x );
OUT_BATCH( (dst_y2 << 16) | dst_x2 );
OUT_BATCH( dst_offset );
OUT_BATCH( (src_y << 16) | src_x );
OUT_BATCH( src_pitch );
OUT_BATCH( src_offset );
ADVANCE_BATCH();
}
void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch)
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
intelScreenPrivate *intelScreen = intel->intelScreen;
GLuint clear_depth, clear_color;
GLint cx, cy;
GLint pitch = intelScreen->front.pitch;
GLint cpp = intelScreen->cpp;
GLint i;
GLuint BR13, CMD, D_CMD;
BATCH_LOCALS;
clear_color = intel->ClearColor;
clear_depth = 0;
if (flags & BUFFER_BIT_DEPTH) {
clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
}
if (flags & BUFFER_BIT_STENCIL) {
clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
}
switch(cpp) {
case 2:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD |
XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
D_CMD = XY_COLOR_BLT_CMD;
if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
break;
default:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
}
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
/* flip top to bottom */
cy = intel->driDrawable->h-cy1-ch;
cx = cx1 + intel->drawX;
cy += intel->drawY;
/* adjust for page flipping */
if ( intel->sarea->pf_current_page == 1 ) {
GLuint tmp = flags;
flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
if ( tmp & BUFFER_BIT_BACK_LEFT ) flags |= BUFFER_BIT_FRONT_LEFT;
}
for (i = 0 ; i < intel->numClipRects ; i++)
{
drm_clip_rect_t *box = &intel->pClipRects[i];
drm_clip_rect_t b;
if (!all) {
GLint x = box[i].x1;
GLint y = box[i].y1;
GLint w = box[i].x2 - x;
GLint h = box[i].y2 - y;
if (x < cx) w -= cx - x, x = cx;
if (y < cy) h -= cy - y, y = cy;
if (x + w > cx + cw) w = cx + cw - x;
if (y + h > cy + ch) h = cy + ch - y;
if (w <= 0) continue;
if (h <= 0) continue;
b.x1 = x;
b.y1 = y;
b.x2 = x + w;
b.y2 = y + h;
} else {
b = *box;
}
if (b.x1 > b.x2 ||
b.y1 > b.y2 ||
b.x2 > intelScreen->width ||
b.y2 > intelScreen->height)
continue;
if ( flags & BUFFER_BIT_FRONT_LEFT ) {
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->front.offset );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & BUFFER_BIT_BACK_LEFT ) {
BEGIN_BATCH( 6);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->back.offset );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
BEGIN_BATCH( 6);
OUT_BATCH( D_CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_BATCH( intelScreen->depth.offset );
OUT_BATCH( clear_depth );
ADVANCE_BATCH();
}
}
}
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
UNLOCK_HARDWARE( intel );
}
void intelDestroyBatchBuffer( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (intel->alloc.ptr) {
intelFreeAGP( intel, intel->alloc.ptr );
intel->alloc.ptr = 0;
}
}
void intelInitBatchBuffer( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) {
intel->alloc.size = 8 * 1024;
intel->alloc.ptr = malloc( intel->alloc.size );
intel->alloc.offset = 0;
if (used & 4) {
((int *)batch->ptr)[0] = intel->vtbl.flush_cmd();
((int *)batch->ptr)[1] = 0;
((int *)batch->ptr)[2] = MI_BATCH_BUFFER_END;
used += 12;
}
else {
switch (intel->intelScreen->deviceID) {
case PCI_CHIP_I865_G:
/* HW bug? Seems to crash if batchbuffer crosses 4k boundary.
*/
intel->alloc.size = 8 * 1024;
break;
default:
/* This is the smallest amount of memory the kernel deals with.
* We'd ideally like to make this smaller.
*/
intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
break;
}
intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
if (intel->alloc.ptr)
intel->alloc.offset =
intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
((int *)batch->ptr)[0] = intel->vtbl.flush_cmd();
((int *)batch->ptr)[1] = MI_BATCH_BUFFER_END;
used += 8;
}
if (!intel->alloc.ptr) {
FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1);
bmUnmapBuffer(batch->bm, batch->buffer);
batch->ptr = NULL;
batch->map = NULL;
/* TODO: Just pass the relocation list and dma buffer up to the
* kernel.
*/
if (!intel->locked)
{
assert(!(batch->flags & INTEL_BATCH_NO_CLIPRECTS));
LOCK_HARDWARE(intel);
do_flush_locked(batch, used, GL_FALSE);
UNLOCK_HARDWARE(intel);
}
else {
intel->prim.flush = 0;
intel->vtbl.emit_invarient_state( intel );
assert(!(batch->flags & INTEL_BATCH_CLIPRECTS));
/* Make sure this gets to the hardware, even if we have no cliprects:
*/
LOCK_HARDWARE( intel );
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
UNLOCK_HARDWARE( intel );
do_flush_locked(batch, used, GL_TRUE);
}
/* Reset the buffer:
*/
intel_batchbuffer_reset( batch );
return batch->last_fence;
}
void intel_batchbuffer_finish( struct intel_batchbuffer *batch )
{
bmFinishFence(batch->bm,
intel_batchbuffer_flush(batch));
}
/* This is the only way buffers get added to the validate list.
*/
GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch,
GLuint buffer,
GLuint flags,
GLuint delta )
{
GLuint i;
assert(batch->nr_relocs <= MAX_RELOCS);
for (i = 0; i < batch->list->nr; i++)
if (buffer == batch->list->elem[i].buffer)
break;
if (i == batch->list->nr) {
if (i == BM_LIST_MAX)
return GL_FALSE;
bmAddBuffer(batch->list,
buffer,
flags,
NULL,
&batch->offset[i]);
}
{
struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
r->offset = batch->ptr - batch->map;
r->delta = delta;
r->elem = i;
}
batch->ptr += 4;
return GL_TRUE;
}
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data,
GLuint bytes,
GLuint flags)
{
assert((bytes & 3) == 0);
intel_batchbuffer_require_space(batch, bytes, flags);
__memcpy(batch->ptr, data, bytes);
batch->ptr += bytes;
}

View File

@@ -1,123 +1,113 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H
#include "intel_context.h"
#include "intel_ioctl.h"
#include "mtypes.h"
#include "bufmgr.h"
struct intel_context;
#define BATCH_SZ 4096
#define BATCH_RESERVED 16
#define MAX_RELOCS 100
#define INTEL_BATCH_NO_CLIPRECTS 0x1
#define INTEL_BATCH_CLIPRECTS 0x2
struct buffer_reloc {
GLuint offset;
GLuint elem; /* elem in buffer list, not buffer id */
GLuint delta; /* not needed? */
};
struct intel_batchbuffer {
struct bufmgr *bm;
struct intel_context *intel;
GLuint buffer;
GLuint last_fence;
GLuint flags;
/* In progress:
*/
GLuint offset[BM_LIST_MAX];
struct bm_buffer_list *list;
GLubyte *map;
GLubyte *ptr;
struct buffer_reloc reloc[MAX_RELOCS];
GLuint nr_relocs;
};
struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel );
void intel_batchbuffer_free( struct intel_batchbuffer *batch );
#define BATCH_LOCALS GLubyte *batch_ptr;
void intel_batchbuffer_finish( struct intel_batchbuffer *batch );
/* #define VERBOSE 0 */
#ifndef VERBOSE
extern int VERBOSE;
#endif
GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch );
#define BEGIN_BATCH(n) \
do { \
if (VERBOSE) fprintf(stderr, \
"BEGIN_BATCH(%d) in %s, %d dwords free\n", \
(n), __FUNCTION__, intel->batch.space/4); \
if (intel->batch.space < (n)*4) \
intelFlushBatch(intel, GL_TRUE); \
batch_ptr = intel->batch.ptr; \
} while (0)
/* Unlike bmBufferData, this currently requires the buffer be mapped.
* Consider it a convenience function wrapping multple
* intel_buffer_dword() calls.
*/
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data,
GLuint bytes,
GLuint flags);
#define OUT_BATCH(n) \
do { \
*(GLuint *)batch_ptr = (n); \
if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__); \
batch_ptr += 4; \
} while (0)
void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
GLuint bytes);
#define ADVANCE_BATCH() \
do { \
if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n"); \
intel->batch.space -= (batch_ptr - intel->batch.ptr); \
intel->batch.ptr = batch_ptr; \
assert(intel->batch.space >= 0); \
} while(0)
GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch,
GLuint buffer,
GLuint flags,
GLuint offset );
extern void intelInitBatchBuffer( GLcontext *ctx );
extern void intelDestroyBatchBuffer( GLcontext *ctx );
extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim );
extern void intelWrapInlinePrimitive( intelContextPtr intel );
extern void intelRestartInlinePrimitive( intelContextPtr intel );
extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
int primitive, int dwords,
int vertex_size);
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch);
extern void intelEmitCopyBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_offset,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
GLshort w, GLshort h );
extern void intelEmitFillBlitLocked( intelContextPtr intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color );
static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,
GLuint dwords )
/* Inline functions - might actually be better off with these
* non-inlined. Certainly better off switching all command packets to
* be passed as structs rather than dwords, but that's a little bit of
* work...
*/
static inline GLuint
intel_batchbuffer_space( struct intel_batchbuffer *batch )
{
GLuint sz = dwords * sizeof(GLuint);
GLuint *ptr;
if (intel->batch.space < sz) {
intelWrapInlinePrimitive( intel );
/* assert(intel->batch.space >= sz); */
}
/* assert(intel->prim.primitive != ~0); */
ptr = (GLuint *)intel->batch.ptr;
intel->batch.ptr += sz;
intel->batch.space -= sz;
return ptr;
return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->map);
}
static inline void
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch,
GLuint dword)
{
assert(batch->map);
assert(intel_batchbuffer_space(batch) >= 4);
*(GLuint *)(batch->ptr) = dword;
batch->ptr += 4;
}
static inline void
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
GLuint sz,
GLuint flags)
{
assert(sz < BATCH_SZ - 8);
if (intel_batchbuffer_space(batch) < sz ||
(batch->flags != 0 && flags != 0 && batch->flags != flags))
intel_batchbuffer_flush(batch);
batch->flags |= flags;
}
/* Here are the crusty old macros, to be removed:
*/
#define BATCH_LOCALS
#define BEGIN_BATCH(n, flags) intel_batchbuffer_require_space(intel->batch, n*4, flags)
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
#define OUT_RELOC(buf,flags,delta) intel_batchbuffer_emit_reloc(intel->batch, buf, flags, delta)
#define ADVANCE_BATCH() do { } while(0)
#endif

View File

@@ -0,0 +1,384 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include <stdio.h>
#include <errno.h>
#include "mtypes.h"
#include "context.h"
#include "enums.h"
#include "intel_reg.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "bufmgr.h"
/*
* Copy the back buffer to the front buffer.
*/
void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
{
struct intel_context *intel;
DBG("%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
bmFinishFence(intel->bm, intel->last_swap_fence);
/* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
* should work regardless.
*/
LOCK_HARDWARE( intel );
{
intelScreenPrivate *intelScreen = intel->intelScreen;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *pbox = dPriv->pClipRects;
int pitch = intelScreen->front.pitch;
int cpp = intelScreen->cpp;
int BR13, CMD;
int i;
if (cpp == 2) {
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
}
else {
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
}
for (i = 0 ; i < nbox; i++, pbox++)
{
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
pbox->x2 > intelScreen->width ||
pbox->y2 > intelScreen->height)
continue;
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
if (intel->sarea->pf_current_page == 0)
OUT_RELOC( intel->front_region->buffer, BM_MEM_AGP|BM_WRITE, 0 );
else
OUT_RELOC( intel->back_region->buffer, BM_MEM_AGP|BM_WRITE, 0 );
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
OUT_BATCH( BR13 & 0xffff );
if (intel->sarea->pf_current_page == 0)
OUT_RELOC( intel->back_region->buffer, BM_MEM_AGP|BM_READ, 0 );
else
OUT_RELOC( intel->front_region->buffer, BM_MEM_AGP|BM_READ, 0 );
ADVANCE_BATCH();
}
}
intel->last_swap_fence = intel_batchbuffer_flush( intel->batch );
UNLOCK_HARDWARE( intel );
}
void intelEmitFillBlit( struct intel_context *intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color )
{
GLuint BR13, CMD;
BATCH_LOCALS;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
break;
default:
return;
}
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (y << 16) | x );
OUT_BATCH( ((y+h) << 16) | (x+w) );
OUT_RELOC( dst_buffer, BM_MEM_AGP|BM_WRITE, dst_offset );
OUT_BATCH( color );
ADVANCE_BATCH();
}
/* Copy BitBlt
*/
void intelEmitCopyBlit( struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_buffer,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort src_x, GLshort src_y,
GLshort dst_x, GLshort dst_y,
GLshort w, GLshort h )
{
GLuint CMD, BR13;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
BATCH_LOCALS;
DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d\n",
__FUNCTION__,
src_buffer, src_pitch, src_x, src_y,
dst_buffer, dst_pitch, dst_x, dst_y,
w,h);
src_pitch *= cpp;
dst_pitch *= cpp;
switch(cpp) {
case 1:
case 2:
case 3:
BR13 = dst_pitch | (0xCC << 16) | (1<<24);
CMD = XY_SRC_COPY_BLT_CMD;
break;
case 4:
BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
break;
default:
return;
}
if (dst_y2 < dst_y ||
dst_x2 < dst_x) {
return;
}
/* Initial y values don't seem to work with negative pitches. If
* we adjust the offsets manually (below), it seems to work fine.
*/
if (0) {
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (dst_y << 16) | dst_x );
OUT_BATCH( (dst_y2 << 16) | dst_x2 );
OUT_RELOC( dst_buffer, BM_MEM_AGP|BM_WRITE, dst_offset );
OUT_BATCH( (src_y << 16) | src_x );
OUT_BATCH( ((GLint)src_pitch&0xffff) );
OUT_RELOC( src_buffer, BM_MEM_AGP|BM_READ, src_offset );
ADVANCE_BATCH();
}
else {
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (0 << 16) | dst_x );
OUT_BATCH( (h << 16) | dst_x2 );
OUT_RELOC( dst_buffer, BM_MEM_AGP|BM_WRITE, dst_offset + dst_y * dst_pitch );
OUT_BATCH( (0 << 16) | src_x );
OUT_BATCH( ((GLint)src_pitch&0xffff) );
OUT_RELOC( src_buffer, BM_MEM_AGP|BM_READ, src_offset + src_y * src_pitch );
ADVANCE_BATCH();
}
}
void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch)
{
struct intel_context *intel = intel_context( ctx );
intelScreenPrivate *intelScreen = intel->intelScreen;
GLuint clear_depth, clear_color;
GLint cx, cy;
GLint pitch = intelScreen->front.pitch;
GLint cpp = intelScreen->cpp;
GLint i;
GLuint BR13, CMD, D_CMD;
BATCH_LOCALS;
clear_color = intel->ClearColor;
clear_depth = 0;
if (flags & BUFFER_BIT_DEPTH) {
clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
}
if (flags & BUFFER_BIT_STENCIL) {
clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
}
switch(cpp) {
case 2:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
case 4:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
CMD = (XY_COLOR_BLT_CMD |
XY_COLOR_BLT_WRITE_ALPHA |
XY_COLOR_BLT_WRITE_RGB);
D_CMD = XY_COLOR_BLT_CMD;
if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
break;
default:
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
D_CMD = CMD = XY_COLOR_BLT_CMD;
break;
}
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
/* flip top to bottom */
cy = intel->driDrawable->h-cy1-ch;
cx = cx1 + intel->drawX;
cy += intel->drawY;
/* adjust for page flipping */
if ( intel->sarea->pf_current_page == 1 ) {
GLuint tmp = flags;
flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
if ( tmp & BUFFER_BIT_BACK_LEFT ) flags |= BUFFER_BIT_FRONT_LEFT;
}
for (i = 0 ; i < intel->numClipRects ; i++)
{
drm_clip_rect_t *box = &intel->pClipRects[i];
drm_clip_rect_t b;
if (!all) {
GLint x = box[i].x1;
GLint y = box[i].y1;
GLint w = box[i].x2 - x;
GLint h = box[i].y2 - y;
if (x < cx) w -= cx - x, x = cx;
if (y < cy) h -= cy - y, y = cy;
if (x + w > cx + cw) w = cx + cw - x;
if (y + h > cy + ch) h = cy + ch - y;
if (w <= 0) continue;
if (h <= 0) continue;
b.x1 = x;
b.y1 = y;
b.x2 = x + w;
b.y2 = y + h;
} else {
b = *box;
}
if (b.x1 > b.x2 ||
b.y1 > b.y2 ||
b.x2 > intelScreen->width ||
b.y2 > intelScreen->height)
continue;
if ( flags & BUFFER_BIT_FRONT_LEFT ) {
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_RELOC( intel->front_region->buffer, BM_MEM_AGP|BM_WRITE, 0 );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & BUFFER_BIT_BACK_LEFT ) {
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_RELOC( intel->back_region->buffer, BM_MEM_AGP|BM_WRITE, 0 );
OUT_BATCH( clear_color );
ADVANCE_BATCH();
}
if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH( D_CMD );
OUT_BATCH( BR13 );
OUT_BATCH( (b.y1 << 16) | b.x1 );
OUT_BATCH( (b.y2 << 16) | b.x2 );
OUT_RELOC( intel->depth_region->buffer, BM_MEM_AGP|BM_WRITE, 0 );
OUT_BATCH( clear_depth );
ADVANCE_BATCH();
}
}
}
intel_batchbuffer_flush( intel->batch );
UNLOCK_HARDWARE( intel );
}

View File

@@ -0,0 +1,60 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#ifndef INTEL_BLIT_H
#define INTEL_BLIT_H
#include "intel_context.h"
#include "intel_ioctl.h"
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch);
extern void intelEmitCopyBlit( struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_buffer,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
GLshort w, GLshort h );
extern void intelEmitFillBlit( struct intel_context *intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color );
#endif

View File

@@ -0,0 +1,505 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_blit.h"
#include "intel_tris.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
#include "context.h"
#include "framebuffer.h"
#include "swrast/swrast.h"
GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst,
const drm_clip_rect_t *a,
const drm_clip_rect_t *b )
{
GLint bx = b->x1;
GLint by = b->y1;
GLint bw = b->x2 - bx;
GLint bh = b->y2 - by;
if (bx < a->x1) bw -= a->x1 - bx, bx = a->x1;
if (by < a->y1) bh -= a->y1 - by, by = a->y1;
if (bx + bw > a->x2) bw = a->x2 - bx;
if (by + bh > a->y2) bh = a->y2 - by;
if (bw <= 0) return GL_FALSE;
if (bh <= 0) return GL_FALSE;
dst->x1 = bx;
dst->y1 = by;
dst->x2 = bx + bw;
dst->y2 = by + bh;
return GL_TRUE;
}
struct intel_region *intel_drawbuf_region( struct intel_context *intel )
{
switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
case BUFFER_BIT_FRONT_LEFT:
return intel->front_region;
case BUFFER_BIT_BACK_LEFT:
return intel->back_region;
default:
/* Not necessary to fallback - could handle either NONE or
* FRONT_AND_BACK cases below.
*/
return NULL;
}
}
struct intel_region *intel_readbuf_region( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
/* This will have to change to support EXT_fbo's, but is correct
* for now:
*/
switch (ctx->ReadBuffer->_ColorReadBufferIndex) {
case BUFFER_FRONT_LEFT:
return intel->front_region;
case BUFFER_BACK_LEFT:
return intel->back_region;
default:
assert(0);
return NULL;
}
}
static void intelBufferSize(GLframebuffer *buffer,
GLuint *width,
GLuint *height)
{
GET_CURRENT_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
/* Need to lock to make sure the driDrawable is uptodate. This
* information is used to resize Mesa's software buffers, so it has
* to be correct.
*/
LOCK_HARDWARE(intel);
if (intel->driDrawable) {
*width = intel->driDrawable->w;
*height = intel->driDrawable->h;
}
else {
*width = 0;
*height = 0;
}
UNLOCK_HARDWARE(intel);
}
static void intelSetFrontClipRects( struct intel_context *intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
}
static void intelSetBackClipRects( struct intel_context *intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
} else {
intel->numClipRects = dPriv->numBackClipRects;
intel->pClipRects = dPriv->pBackClipRects;
intel->drawX = dPriv->backX;
intel->drawY = dPriv->backY;
if (dPriv->numBackClipRects == 1 &&
dPriv->x == dPriv->backX &&
dPriv->y == dPriv->backY) {
/* Repeat the calculation of the back cliprect dimensions here
* as early versions of dri.a in the Xserver are incorrect. Try
* very hard not to restrict future versions of dri.a which
* might eg. allocate truly private back buffers.
*/
int x1, y1;
int x2, y2;
x1 = dPriv->x;
y1 = dPriv->y;
x2 = dPriv->x + dPriv->w;
y2 = dPriv->y + dPriv->h;
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
if (x1 == dPriv->pBackClipRects[0].x1 &&
y1 == dPriv->pBackClipRects[0].y1) {
dPriv->pBackClipRects[0].x2 = x2;
dPriv->pBackClipRects[0].y2 = y2;
}
}
}
}
void intelWindowMoved( struct intel_context *intel )
{
if (!intel->ctx.DrawBuffer) {
intelSetFrontClipRects( intel );
}
else {
switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
case BUFFER_BIT_FRONT_LEFT:
intelSetFrontClipRects( intel );
break;
case BUFFER_BIT_BACK_LEFT:
intelSetBackClipRects( intel );
break;
default:
/* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
intelSetFrontClipRects( intel );
}
}
/* Set state we know depends on drawable parameters:
*/
{
GLcontext *ctx = &intel->ctx;
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.DepthRange( ctx,
ctx->Viewport.Near,
ctx->Viewport.Far );
}
}
static void emit_clip_rect_quads(struct intel_context *intel,
const drm_clip_rect_t *clear)
{
GLuint i;
for (i = 0; i < intel->numClipRects; i++) {
drm_clip_rect_t rect;
if (intel_intersect_cliprects(&rect,
clear,
&intel->pClipRects[i]))
{
intel_meta_draw_quad(intel,
rect.x1, rect.x2,
rect.y1, rect.y2,
0,
intel->ClearColor,
0, 0, 0, 0,
INTEL_BATCH_NO_CLIPRECTS);
}
}
}
/* A true meta version of this would be very simple and additionally
* machine independent. Maybe we'll get there one day.
*/
static void intelClearWithTris(struct intel_context *intel,
GLbitfield mask,
GLboolean all,
GLint cx, GLint cy,
GLint cw, GLint ch)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
drm_clip_rect_t clear;
LOCK_HARDWARE(intel);
intel->vtbl.install_meta_state(intel);
if(!all) {
clear.x1 = cx;
clear.y1 = cy;
clear.x2 = cx + cw;
clear.y2 = cy + ch;
} else {
clear.x1 = 0;
clear.y1 = 0;
clear.x2 = dPriv->w;
clear.y2 = dPriv->h;
}
/* Back and stencil cliprects are the same. Try and do both
* buffers at once:
*/
if (mask & (BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL)) {
intel->vtbl.meta_draw_region(intel,
intel->back_region,
intel->depth_region );
if (mask & BUFFER_BIT_BACK_LEFT)
intel->vtbl.meta_color_mask(intel, GL_TRUE );
else
intel->vtbl.meta_color_mask(intel, GL_FALSE );
if (mask & BUFFER_BIT_STENCIL)
intel->vtbl.meta_stencil_replace( intel,
intel->ctx.Stencil.WriteMask[0],
intel->ctx.Stencil.Clear);
else
intel->vtbl.meta_no_depth_stencil_write(intel);
/* Do cliprects explicitly:
*/
emit_clip_rect_quads(intel, &clear);
}
/* Front may have different cliprects:
*/
if (mask & BUFFER_BIT_FRONT_LEFT) {
intel->vtbl.meta_no_depth_stencil_write(intel);
intel->vtbl.meta_color_mask(intel, GL_TRUE );
intel->vtbl.meta_draw_region(intel,
intel->front_region,
intel->depth_region);
emit_clip_rect_quads(intel, &clear);
}
intel->vtbl.leave_meta_state( intel );
intel_batchbuffer_flush( intel->batch );
UNLOCK_HARDWARE(intel);
}
static void intelClear(GLcontext *ctx,
GLbitfield mask,
GLboolean all,
GLint cx, GLint cy,
GLint cw, GLint ch)
{
struct intel_context *intel = intel_context( ctx );
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
GLbitfield tri_mask = 0;
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
if (mask & BUFFER_BIT_FRONT_LEFT) {
if (colorMask == ~0) {
blit_mask |= BUFFER_BIT_FRONT_LEFT;
}
else {
tri_mask |= BUFFER_BIT_FRONT_LEFT;
}
}
if (mask & BUFFER_BIT_BACK_LEFT) {
if (colorMask == ~0) {
blit_mask |= BUFFER_BIT_BACK_LEFT;
}
else {
tri_mask |= BUFFER_BIT_BACK_LEFT;
}
}
if (mask & BUFFER_BIT_DEPTH) {
blit_mask |= BUFFER_BIT_DEPTH;
}
if (mask & BUFFER_BIT_STENCIL) {
if (!intel->hw_stencil) {
swrast_mask |= BUFFER_BIT_STENCIL;
}
else if (ctx->Stencil.WriteMask[0] != 0xff) {
tri_mask |= BUFFER_BIT_STENCIL;
}
else {
blit_mask |= BUFFER_BIT_STENCIL;
}
}
swrast_mask |= (mask & BUFFER_BIT_ACCUM);
intelFlush( ctx );
if (blit_mask)
intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
if (tri_mask)
intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch);
if (swrast_mask)
_swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
}
/* Flip the front & back buffers
*/
static void intelPageFlip( const __DRIdrawablePrivate *dPriv )
{
#if 0
struct intel_context *intel;
int tmp, ret;
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (dPriv->pClipRects) {
*(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
intel->sarea->nbox = 1;
}
ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
if (ret) {
fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE( intel );
exit(1);
}
tmp = intel->sarea->last_enqueue;
intelRefillBatchLocked( intel );
UNLOCK_HARDWARE( intel );
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
#endif
}
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
struct intel_context *intel;
GLcontext *ctx;
intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
ctx = &intel->ctx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
intelPageFlip( dPriv );
} else {
intelCopyBuffer( dPriv );
}
}
} else {
/* XXX this shouldn't be an error but we can't handle it for now */
fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
}
}
static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
{
struct intel_context *intel = intel_context(ctx);
int front = 0;
if (!ctx->DrawBuffer)
return;
switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
case BUFFER_BIT_FRONT_LEFT:
front = 1;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
case BUFFER_BIT_BACK_LEFT:
front = 0;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
default:
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
return;
}
if ( intel->sarea->pf_current_page == 1 )
front ^= 1;
intelSetFrontClipRects( intel );
if (front) {
if (intel->draw_region != intel->front_region) {
intel_region_release(intel, &intel->draw_region);
intel_region_reference(&intel->draw_region, intel->front_region);
}
} else {
if (intel->draw_region != intel->back_region) {
intel_region_release(intel, &intel->draw_region);
intel_region_reference(&intel->draw_region, intel->back_region);
}
}
intel->vtbl.set_draw_region( intel,
intel->draw_region,
intel->depth_region);
}
static void intelReadBuffer( GLcontext *ctx, GLenum mode )
{
/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
}
void intelInitBufferFuncs( struct dd_function_table *functions )
{
functions->Clear = intelClear;
functions->GetBufferSize = intelBufferSize;
functions->ResizeBuffers = _mesa_resize_framebuffer;
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
}

View File

@@ -54,6 +54,11 @@
#include "intel_tris.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_pixel.h"
#include "intel_regions.h"
#include "bufmgr.h"
#include "utils.h"
#ifndef INTEL_DEBUG
@@ -77,9 +82,6 @@ int INTEL_DEBUG = (0);
#define need_GL_NV_vertex_program
#include "extension_helper.h"
#ifndef VERBOSE
int VERBOSE = 0;
#endif
#if DEBUG_LOCKING
char *prevLockFile;
@@ -90,9 +92,9 @@ int prevLockLine;
* Mesa's Driver Functions
***************************************/
#define DRIVER_DATE "20050225"
#define DRIVER_DATE "20060212"
const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
static const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
{
const char * chipset;
static char buffer[128];
@@ -103,7 +105,7 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
break;
case GL_RENDERER:
switch (INTEL_CONTEXT(ctx)->intelScreen->deviceID) {
switch (intel_context(ctx)->intelScreen->deviceID) {
case PCI_CHIP_845_G:
chipset = "Intel(R) 845G"; break;
case PCI_CHIP_I830_M:
@@ -130,27 +132,6 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
}
}
static void intelBufferSize(GLframebuffer *buffer,
GLuint *width, GLuint *height)
{
GET_CURRENT_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
/* Need to lock to make sure the driDrawable is uptodate. This
* information is used to resize Mesa's software buffers, so it has
* to be correct.
*/
LOCK_HARDWARE(intel);
if (intel->driDrawable) {
*width = intel->driDrawable->w;
*height = intel->driDrawable->h;
}
else {
*width = 0;
*height = 0;
}
UNLOCK_HARDWARE(intel);
}
/**
* Extension strings exported by the intel driver.
@@ -197,7 +178,7 @@ const struct dri_extension card_extensions[] =
{ "GL_NV_blend_square", NULL },
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions },
{ "GL_NV_vertex_program1_1", NULL },
{ "GL_SGIS_generate_mipmap", NULL },
/* { "GL_SGIS_generate_mipmap", NULL }, */
{ NULL, NULL }
};
@@ -214,7 +195,7 @@ static const struct tnl_pipeline_stage *intel_pipeline[] = {
&_tnl_point_attenuation_stage,
&_tnl_arb_vertex_program_stage,
&_tnl_vertex_program_stage,
#if 1
#if 0
&_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */
#endif
&_tnl_render_stage,
@@ -237,6 +218,7 @@ static const struct dri_debug_control debug_control[] =
{ "sync", DEBUG_SYNC },
{ "sleep", DEBUG_SLEEP },
{ "pix", DEBUG_PIXEL },
{ "buf", DEBUG_BUFMGR },
{ NULL, 0 }
};
@@ -248,7 +230,32 @@ static void intelInvalidateState( GLcontext *ctx, GLuint new_state )
_ac_InvalidateState( ctx, new_state );
_tnl_InvalidateState( ctx, new_state );
_tnl_invalidate_vertex_state( ctx, new_state );
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
intel_context(ctx)->NewGLState |= new_state;
}
void intelFlush( GLcontext *ctx )
{
struct intel_context *intel = intel_context( ctx );
if (intel->Fallback)
_swrast_flush( ctx );
INTEL_FIREVERTICES( intel );
if (intel->batch->map != intel->batch->ptr)
intel_batchbuffer_flush( intel->batch );
/* XXX: Need to do an MI_FLUSH here. Actually, the bufmgr_fake.c
* code will have done one already.
*/
}
void intelFinish( GLcontext *ctx )
{
struct intel_context *intel = intel_context( ctx );
intelFlush( ctx );
bmFinishFence( intel->bm, intel->last_fence );
}
@@ -257,10 +264,7 @@ void intelInitDriverFunctions( struct dd_function_table *functions )
_mesa_init_driver_functions( functions );
functions->Flush = intelFlush;
functions->Clear = intelClear;
functions->Finish = intelFinish;
functions->GetBufferSize = intelBufferSize;
functions->ResizeBuffers = _mesa_resize_framebuffer;
functions->GetString = intelGetString;
functions->UpdateState = intelInvalidateState;
functions->CopyColorTable = _swrast_CopyColorTable;
@@ -271,11 +275,12 @@ void intelInitDriverFunctions( struct dd_function_table *functions )
intelInitTextureFuncs( functions );
intelInitPixelFuncs( functions );
intelInitStateFuncs( functions );
intelInitBufferFuncs( functions );
}
GLboolean intelInitContext( intelContextPtr intel,
GLboolean intelInitContext( struct intel_context *intel,
const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate,
@@ -300,9 +305,6 @@ GLboolean intelInitContext( intelContextPtr intel,
intel->sarea = saPriv;
(void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) );
make_empty_list( & intel->swapped );
ctx->Const.MaxTextureMaxAnisotropy = 2.0;
ctx->Const.MinLineWidth = 1.0;
@@ -371,7 +373,57 @@ GLboolean intelInitContext( intelContextPtr intel,
_math_matrix_ctr (&intel->ViewportMatrix);
driInitExtensions( ctx, card_extensions, GL_TRUE );
/* Disable imaging extension until convolution is working in
* teximage paths:
*/
driInitExtensions( ctx, card_extensions,
/* GL_TRUE, */
GL_FALSE);
/* Buffer manager:
*/
intel->bm = bm_fake_intel_Attach( intel );
bmInitPool(intel->bm,
intel->intelScreen->tex.offset, /* low offset */
intel->intelScreen->tex.map, /* low virtual */
intel->intelScreen->tex.size,
BM_MEM_AGP);
/* These are still static, but create regions for them.
*/
intel->front_region =
intel_region_create_static(intel,
BM_MEM_AGP,
intelScreen->front.offset,
intelScreen->front.map,
intelScreen->cpp,
intelScreen->front.pitch,
intelScreen->height);
intel->back_region =
intel_region_create_static(intel,
BM_MEM_AGP,
intelScreen->back.offset,
intelScreen->back.map,
intelScreen->cpp,
intelScreen->back.pitch,
intelScreen->height);
/* Still assuming front.cpp == depth.cpp
*/
intel->depth_region =
intel_region_create_static(intel,
BM_MEM_AGP,
intelScreen->depth.offset,
intelScreen->depth.map,
intelScreen->cpp,
intelScreen->depth.pitch,
intelScreen->height);
intel->batch = intel_batchbuffer_alloc( intel );
if (intel->ctx.Mesa_DXTn) {
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
@@ -387,24 +439,16 @@ GLboolean intelInitContext( intelContextPtr intel,
/* DRI_TEXMGR_DO_TEXTURE_RECT ); */
intel->prim.flush = intelInitBatchBuffer;
intel->prim.primitive = ~0;
#if DO_DEBUG
INTEL_DEBUG = driParseDebugString( getenv( "INTEL_DEBUG" ),
debug_control );
INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
debug_control );
#endif
#ifndef VERBOSE
if (getenv("INTEL_VERBOSE"))
VERBOSE=1;
#endif
if (getenv("INTEL_NO_RAST") ||
getenv("INTEL_NO_RAST")) {
if (getenv("INTEL_NO_RAST")) {
fprintf(stderr, "disabling 3D rasterization\n");
FALLBACK(intel, INTEL_FALLBACK_USER, 1);
}
@@ -414,7 +458,7 @@ GLboolean intelInitContext( intelContextPtr intel,
void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
{
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate;
assert(intel); /* should never be null */
if (intel) {
@@ -431,21 +475,14 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
_swrast_DestroyContext (&intel->ctx);
intel->Fallback = 0; /* don't call _swrast_Flush later */
intelDestroyBatchBuffer(&intel->ctx);
intel_batchbuffer_free(intel->batch);
if ( release_texture_heaps ) {
/* This share group is about to go away, free our private
* texture object data.
*/
int i;
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
driDestroyTextureHeap( intel->texture_heaps[ i ] );
intel->texture_heaps[ i ] = NULL;
}
assert( is_empty_list( & intel->swapped ) );
fprintf(stderr, "do somethign to free texture heaps\n");
}
/* free the Mesa context */
@@ -453,102 +490,6 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
}
}
void intelSetFrontClipRects( intelContextPtr intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
}
void intelSetBackClipRects( intelContextPtr intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
} else {
intel->numClipRects = dPriv->numBackClipRects;
intel->pClipRects = dPriv->pBackClipRects;
intel->drawX = dPriv->backX;
intel->drawY = dPriv->backY;
if (dPriv->numBackClipRects == 1 &&
dPriv->x == dPriv->backX &&
dPriv->y == dPriv->backY) {
/* Repeat the calculation of the back cliprect dimensions here
* as early versions of dri.a in the Xserver are incorrect. Try
* very hard not to restrict future versions of dri.a which
* might eg. allocate truly private back buffers.
*/
int x1, y1;
int x2, y2;
x1 = dPriv->x;
y1 = dPriv->y;
x2 = dPriv->x + dPriv->w;
y2 = dPriv->y + dPriv->h;
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
if (x1 == dPriv->pBackClipRects[0].x1 &&
y1 == dPriv->pBackClipRects[0].y1) {
dPriv->pBackClipRects[0].x2 = x2;
dPriv->pBackClipRects[0].y2 = y2;
}
}
}
}
void intelWindowMoved( intelContextPtr intel )
{
if (!intel->ctx.DrawBuffer) {
intelSetFrontClipRects( intel );
}
else {
switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
case BUFFER_BIT_FRONT_LEFT:
intelSetFrontClipRects( intel );
break;
case BUFFER_BIT_BACK_LEFT:
intelSetBackClipRects( intel );
break;
default:
/* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
intelSetFrontClipRects( intel );
}
}
/* Set state we know depends on drawable parameters:
*/
{
GLcontext *ctx = &intel->ctx;
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.DepthRange( ctx,
ctx->Viewport.Near,
ctx->Viewport.Far );
}
}
GLboolean intelUnbindContext(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
@@ -560,7 +501,7 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
{
if (driContextPriv) {
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate;
if ( intel->driDrawable != driDrawPriv ) {
/* Shouldn't the readbuffer be stored also? */
@@ -580,13 +521,12 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
return GL_TRUE;
}
void intelGetLock( intelContextPtr intel, GLuint flags )
void intelGetLock( struct intel_context *intel, GLuint flags )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
__DRIscreenPrivate *sPriv = intel->driScreen;
drmI830Sarea * sarea = intel->sarea;
int me = intel->hHWContext;
unsigned i;
drmGetLock(intel->driFd, intel->hHWContext, flags);
@@ -598,143 +538,19 @@ void intelGetLock( intelContextPtr intel, GLuint flags )
if (dPriv)
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
/* If we lost context, need to dump all registers to hardware.
* Note that we don't care about 2d contexts, even if they perform
* accelerated commands, so the DRI locking in the X server is even
* more broken than usual.
/* Lost context?
*/
if (sarea->ctxOwner != me) {
intel->perf_boxes |= I830_BOX_LOST_CONTEXT;
sarea->ctxOwner = me;
}
/* Shared texture managment - if another client has played with
* texture space, figure out which if any of our textures have been
* ejected, and update our global LRU.
/* Drawable changed?
*/
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
DRI_AGE_TEXTURES( intel->texture_heaps[ i ] );
}
if (dPriv && intel->lastStamp != dPriv->lastStamp) {
intelWindowMoved( intel );
intel->lastStamp = dPriv->lastStamp;
}
}
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
intelContextPtr intel;
GLcontext *ctx;
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
ctx = &intel->ctx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
intelPageFlip( dPriv );
} else {
intelCopyBuffer( dPriv );
}
}
} else {
/* XXX this shouldn't be an error but we can't handle it for now */
fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
}
}
void intelInitState( GLcontext *ctx )
{
/* Mesa should do this for us:
*/
ctx->Driver.AlphaFunc( ctx,
ctx->Color.AlphaFunc,
ctx->Color.AlphaRef);
ctx->Driver.BlendColor( ctx,
ctx->Color.BlendColor );
ctx->Driver.BlendEquationSeparate( ctx,
ctx->Color.BlendEquationRGB,
ctx->Color.BlendEquationA);
ctx->Driver.BlendFuncSeparate( ctx,
ctx->Color.BlendSrcRGB,
ctx->Color.BlendDstRGB,
ctx->Color.BlendSrcA,
ctx->Color.BlendDstA);
ctx->Driver.ColorMask( ctx,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP]);
ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
ctx->Driver.DepthFunc( ctx, ctx->Depth.Func );
ctx->Driver.DepthMask( ctx, ctx->Depth.Mask );
ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag );
ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled );
ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled );
ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
{
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
}
ctx->Driver.LineWidth( ctx, ctx->Line.Width );
ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp );
ctx->Driver.PointSize( ctx, ctx->Point.Size );
ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple );
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel );
ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT,
ctx->Stencil.Function[0],
ctx->Stencil.Ref[0],
ctx->Stencil.ValueMask[0] );
ctx->Driver.StencilFuncSeparate( ctx, GL_BACK,
ctx->Stencil.Function[1],
ctx->Stencil.Ref[1],
ctx->Stencil.ValueMask[1] );
ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
ctx->Driver.StencilOpSeparate( ctx, GL_FRONT,
ctx->Stencil.FailFunc[0],
ctx->Stencil.ZFailFunc[0],
ctx->Stencil.ZPassFunc[0]);
ctx->Driver.StencilOpSeparate( ctx, GL_BACK,
ctx->Stencil.FailFunc[1],
ctx->Stencil.ZFailFunc[1],
ctx->Stencil.ZPassFunc[1]);
ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
}

View File

@@ -47,82 +47,123 @@
#define DV_PF_565 (2<<8)
#define DV_PF_8888 (3<<8)
#define INTEL_CONTEXT(ctx) ((intelContextPtr)(ctx))
struct intel_region;
struct intel_context;
typedef struct intel_context intelContext;
typedef struct intel_context *intelContextPtr;
typedef struct intel_texture_object *intelTextureObjectPtr;
typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *,
typedef void (*intel_tri_func)(struct intel_context *, intelVertex *, intelVertex *,
intelVertex *);
typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *);
typedef void (*intel_point_func)(intelContextPtr, intelVertex *);
typedef void (*intel_line_func)(struct intel_context *, intelVertex *, intelVertex *);
typedef void (*intel_point_func)(struct intel_context *, intelVertex *);
#define INTEL_FALLBACK_DRAW_BUFFER 0x1
#define INTEL_FALLBACK_READ_BUFFER 0x2
#define INTEL_FALLBACK_USER 0x4
#define INTEL_FALLBACK_NO_BATCHBUFFER 0x8
#define INTEL_FALLBACK_NO_TEXMEM 0x10
#define INTEL_FALLBACK_RENDERMODE 0x20
#define INTEL_FALLBACK_RENDERMODE 0x8
extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode );
extern void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode );
#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode )
#define INTEL_TEX_MAXLEVELS 10
struct intel_texture_object
{
driTextureObject base; /* the parent class */
struct gl_texture_object base; /* The "parent" object */
GLuint texelBytes;
GLuint age;
GLuint Pitch;
GLuint Height;
GLuint TextureOffset;
GLubyte *BufAddr;
/* The mipmap tree must include at least these levels once
* validated:
*/
GLuint firstLevel;
GLuint lastLevel;
GLuint min_level;
GLuint max_level;
GLuint depth_pitch;
/* Offset for firstLevel image:
*/
GLuint textureOffset;
struct {
const struct gl_texture_image *image;
GLuint offset; /* into BufAddr */
GLuint height;
GLuint internalFormat;
} image[6][INTEL_TEX_MAXLEVELS];
GLuint dirty;
GLuint firstLevel,lastLevel;
/* On validation any active images held in main memory or in other
* regions will be copied to this region and the old storage freed.
*/
struct intel_mipmap_tree *mt;
};
struct intel_texture_image
{
struct gl_texture_image base;
/* These aren't stored in gl_texture_image
*/
GLuint level;
GLuint face;
/* If intelImage->mt != NULL, image data is stored here.
* Else if intelImage->base.Data != NULL, image is stored there.
* Else there is no image data.
*/
struct intel_mipmap_tree *mt;
};
#define INTEL_MAX_FIXUP 64
struct intel_context
{
GLcontext ctx; /* the parent class */
struct {
void (*destroy)( intelContextPtr intel );
void (*emit_state)( intelContextPtr intel );
void (*emit_invarient_state)( intelContextPtr intel );
void (*lost_hardware)( intelContextPtr intel );
void (*update_texture_state)( intelContextPtr intel );
void (*destroy)( struct intel_context *intel );
void (*emit_state)( struct intel_context *intel );
void (*emit_invarient_state)( struct intel_context *intel );
void (*lost_hardware)( struct intel_context *intel );
void (*update_texture_state)( struct intel_context *intel );
void (*render_start)( intelContextPtr intel );
void (*set_draw_offset)( intelContextPtr intel, int offset );
void (*emit_flush)( intelContextPtr intel );
void (*render_start)( struct intel_context *intel );
void (*set_draw_region)( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region );
void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim );
GLuint (*flush_cmd)( void );
GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected );
void (*reduced_primitive_state)( struct intel_context *intel, GLenum rprim );
void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask,
GLboolean (*check_vertex_size)( struct intel_context *intel, GLuint expected );
void (*clear_with_tris)( struct intel_context *intel, GLbitfield mask,
GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch);
intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj );
/* Metaops:
*/
void (*install_meta_state)( struct intel_context *intel );
void (*leave_meta_state)( struct intel_context *intel );
void (*meta_draw_region)( struct intel_context *intel,
struct intel_region *draw_region,
struct intel_region *depth_region );
void (*meta_color_mask)( struct intel_context *intel,
GLboolean );
void (*meta_stencil_replace)( struct intel_context *intel,
GLuint mask,
GLuint clear );
void (*meta_no_depth_stencil_write)( struct intel_context *intel );
void (*meta_no_texture)( struct intel_context *intel );
void (*meta_texture_blend_replace)( struct intel_context *intel );
void (*meta_tex_rect_source)( struct intel_context *intel,
struct intel_region *region,
GLuint textureFormat );
void (*meta_draw_format)( struct intel_context *intel,
GLuint format,
GLuint depth_format );
} vtbl;
@@ -130,41 +171,27 @@ struct intel_context
GLuint Fallback;
GLuint NewGLState;
struct {
GLuint start_offset;
GLint size;
GLint space;
GLubyte *ptr;
} batch;
struct {
void *ptr;
GLint size;
GLuint offset;
GLuint active_buf;
GLuint irq_emitted;
} alloc;
GLuint last_fence;
GLuint last_swap_fence;
struct intel_batchbuffer *batch;
struct {
GLuint id;
GLuint primitive;
GLubyte *start_ptr;
void (*flush)( GLcontext * );
void (*flush)( struct intel_context * );
} prim;
GLboolean locked;
GLubyte clear_red;
GLubyte clear_green;
GLubyte clear_blue;
GLubyte clear_alpha;
GLuint ClearColor;
GLuint ClearDepth;
/* Offsets of fields within the current vertex:
*/
GLuint coloroffset;
GLuint specoffset;
/* Support for duplicating XYZW as WPOS parameter (crutch for I915).
*/
GLuint wpos_offset;
GLuint wpos_size;
@@ -179,14 +206,10 @@ struct intel_context
GLboolean hw_stencil;
GLboolean hw_stipple;
/* Texture object bookkeeping
/* AGP memory buffer manager:
*/
GLuint nr_heaps;
driTexHeap * texture_heaps[1];
driTextureObject swapped;
GLuint lastStamp;
struct bufmgr *bm;
struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS];
/* State for intelvb.c and inteltris.c.
*/
@@ -195,7 +218,13 @@ struct intel_context
GLenum render_primitive;
GLenum reduced_primitive;
GLuint vertex_size;
char *verts; /* points to tnl->clipspace.vertex_buf */
GLubyte *verts; /* points to tnl->clipspace.vertex_buf */
struct intel_region *front_region;
struct intel_region *back_region;
struct intel_region *draw_region;
struct intel_region *depth_region;
/* Fallback rasterization functions
@@ -206,13 +235,11 @@ struct intel_context
/* These refer to the current draw (front vs. back) buffer:
*/
GLuint drawOffset; /* agp offset of drawbuffer */
int drawX; /* origin of drawable in draw buffer */
int drawY;
GLuint numClipRects; /* cliprects for that buffer */
drm_clip_rect_t *pClipRects;
int dirtyAge;
int perf_boxes;
int do_irqs;
@@ -228,6 +255,8 @@ struct intel_context
__DRIscreenPrivate *driScreen;
intelScreenPrivate *intelScreen;
drmI830Sarea *sarea;
GLuint lastStamp;
/**
* Configuration cache
@@ -321,8 +350,7 @@ do { \
#define INTEL_FIREVERTICES(intel) \
do { \
if ((intel)->prim.flush) \
(intel)->prim.flush(&(intel)->ctx); \
assert(!(intel)->prim.flush); \
} while (0)
/* ================================================================
@@ -356,7 +384,7 @@ do { \
* than COPY_DWORDS would:
*/
#if defined(i386) || defined(__i386__)
static __inline__ void * __memcpy(void * to, const void * from, size_t n)
static inline void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
@@ -417,21 +445,19 @@ extern int INTEL_DEBUG;
* intel_context.c:
*/
extern void intelInitDriverFunctions( struct dd_function_table *functions );
extern GLboolean intelInitContext( intelContextPtr intel,
extern GLboolean intelInitContext( struct intel_context *intel,
const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate,
struct dd_function_table *functions );
extern void intelGetLock(intelContextPtr intel, GLuint flags);
extern void intelSetBackClipRects(intelContextPtr intel);
extern void intelSetFrontClipRects(intelContextPtr intel);
extern void intelWindowMoved( intelContextPtr intel );
extern void intelGetLock(struct intel_context *intel, GLuint flags);
extern void intelInitState( GLcontext *ctx );
extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name );
extern void intelFinish( GLcontext *ctx );
extern void intelFlush( GLcontext *ctx );
extern void intelInitDriverFunctions( struct dd_function_table *functions );
/* ================================================================
@@ -491,6 +517,8 @@ extern void intelInitStateFuncs( struct dd_function_table *functions );
#define BLENDFACT_INV_CONST_ALPHA 0x0f
#define BLENDFACT_MASK 0x0f
#define MI_BATCH_BUFFER_END (0xA<<23)
extern int intel_translate_compare_func( GLenum func );
extern int intel_translate_stencil_op( GLenum op );
@@ -499,18 +527,39 @@ extern int intel_translate_logic_op( GLenum opcode );
/* ================================================================
* intel_ioctl.c:
* intel_buffers.c:
*/
extern void intel_dump_batchbuffer( long offset,
int *ptr,
int count );
void intelInitBufferFuncs( struct dd_function_table *functions );
struct intel_region *intel_readbuf_region( struct intel_context *intel );
struct intel_region *intel_drawbuf_region( struct intel_context *intel );
extern void intelWindowMoved( struct intel_context *intel );
extern GLboolean intel_intersect_cliprects( drm_clip_rect_t *dest,
const drm_clip_rect_t *a,
const drm_clip_rect_t *b );
/* ================================================================
* intel_pixel.c:
*/
extern void intelInitPixelFuncs( struct dd_function_table *functions );
/*======================================================================
* Inline conversion functions.
* These are better-typed than the macros used previously:
*/
static inline struct intel_context *intel_context( GLcontext *ctx )
{
return (struct intel_context *)ctx;
}
static inline struct intel_texture_object *intel_texture_object( struct gl_texture_object *obj )
{
return (struct intel_texture_object *)obj;
}
static inline struct intel_texture_image *intel_texture_image( struct gl_texture_image *img )
{
return (struct intel_texture_image *)img;
}
#endif

View File

@@ -38,11 +38,13 @@
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "drm.h"
#include "bufmgr.h"
static int intelEmitIrqLocked( intelContextPtr intel )
int intelEmitIrqLocked( struct intel_context *intel )
{
drmI830IrqEmit ie;
int ret, seq = 0;
@@ -51,21 +53,21 @@ static int intelEmitIrqLocked( intelContextPtr intel )
(DRM_LOCK_HELD|intel->hHWContext));
ie.irq_seq = &seq;
ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT,
&ie, sizeof(ie) );
if ( ret ) {
fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret );
exit(1);
}
}
if (0)
fprintf(stderr, "%s --> %d\n", __FUNCTION__, seq );
return seq;
}
static void intelWaitIrq( intelContextPtr intel, int seq )
void intelWaitIrq( struct intel_context *intel, int seq )
{
drmI830IrqWait iw;
int ret;
@@ -81,527 +83,63 @@ static void intelWaitIrq( intelContextPtr intel, int seq )
if ( ret ) {
fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret );
if (0)
intel_dump_batchbuffer( intel->alloc.offset,
intel->alloc.ptr,
intel->alloc.size );
exit(1);
}
}
static void age_intel( intelContextPtr intel, int age )
{
GLuint i;
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
if (intel->CurrentTexObj[i])
intel->CurrentTexObj[i]->age = age;
}
void intel_dump_batchbuffer( long offset,
int *ptr,
int count )
{
int i;
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count);
for (i = 0; i < count/4; i += 4)
fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
(unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]);
fprintf(stderr, "END BATCH\n\n\n");
}
void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock )
{
GLuint last_irq = intel->alloc.irq_emitted;
GLuint half = intel->alloc.size / 2;
GLuint buf = (intel->alloc.active_buf ^= 1);
intel->alloc.irq_emitted = intelEmitIrqLocked( intel );
if (last_irq) {
if (allow_unlock) UNLOCK_HARDWARE( intel );
intelWaitIrq( intel, last_irq );
if (allow_unlock) LOCK_HARDWARE( intel );
}
if (0)
fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf);
intel->batch.start_offset = intel->alloc.offset + buf * half;
intel->batch.ptr = (GLubyte *)intel->alloc.ptr + buf * half;
intel->batch.size = half - 8;
intel->batch.space = half - 8;
assert(intel->batch.space >= 0);
}
#define MI_BATCH_BUFFER_END (0xA<<23)
void intelFlushBatchLocked( intelContextPtr intel,
GLboolean ignore_cliprects,
GLboolean refill,
GLboolean allow_unlock)
void intel_batch_ioctl( struct intel_context *intel,
GLuint start_offset,
GLuint used,
GLboolean ignore_cliprects)
{
drmI830BatchBuffer batch;
assert(intel->locked);
assert(used);
if (0)
fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n",
fprintf(stderr, "%s used %d offset %x..%x ignore_cliprects %d\n",
__FUNCTION__,
(intel->batch.size - intel->batch.space),
intel->batch.size,
intel->batch.start_offset,
intel->batch.start_offset +
(intel->batch.size - intel->batch.space),
refill);
used,
start_offset,
start_offset + used,
ignore_cliprects);
/* Throw away non-effective packets. Won't work once we have
* hardware contexts which would preserve statechanges beyond a
* single buffer.
*/
if (intel->numClipRects == 0 && !ignore_cliprects) {
/* Without this yeild, an application with no cliprects can hog
* the hardware. Without unlocking, the effect is much worse -
* effectively a lock-out of other contexts.
*/
if (allow_unlock) {
UNLOCK_HARDWARE( intel );
sched_yield();
LOCK_HARDWARE( intel );
}
/* Note that any state thought to have been emitted actually
* hasn't:
*/
intel->batch.ptr -= (intel->batch.size - intel->batch.space);
intel->batch.space = intel->batch.size;
intel->vtbl.lost_hardware( intel );
}
if (intel->batch.space != intel->batch.size) {
batch.start = intel->batch.start_offset;
batch.used = intel->batch.size - intel->batch.space;
batch.cliprects = intel->pClipRects;
batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
batch.DR1 = 0;
batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |
(((GLuint)intel->drawY) << 16));
if (intel->alloc.offset) {
if ((batch.used & 0x4) == 0) {
((int *)intel->batch.ptr)[0] = 0;
((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END;
batch.used += 0x8;
intel->batch.ptr += 0x8;
}
else {
((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END;
batch.used += 0x4;
intel->batch.ptr += 0x4;
}
}
if (0)
intel_dump_batchbuffer( batch.start,
(int *)(intel->batch.ptr - batch.used),
batch.used );
if (0)
fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
__FUNCTION__,
batch.start,
batch.start + batch.used,
batch.DR4, batch.num_cliprects);
intel->batch.start_offset += batch.used;
intel->batch.size -= batch.used;
if (intel->batch.size < 8) {
refill = GL_TRUE;
intel->batch.space = intel->batch.size = 0;
}
else {
intel->batch.size -= 8;
intel->batch.space = intel->batch.size;
}
assert(intel->batch.space >= 0);
assert(batch.start >= intel->alloc.offset);
assert(batch.start < intel->alloc.offset + intel->alloc.size);
assert(batch.start + batch.used > intel->alloc.offset);
assert(batch.start + batch.used <=
intel->alloc.offset + intel->alloc.size);
if (intel->alloc.offset) {
if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,
sizeof(batch))) {
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
} else {
drmI830CmdBuffer cmd;
cmd.buf = (char *)intel->alloc.ptr + batch.start;
cmd.sz = batch.used;
cmd.DR1 = batch.DR1;
cmd.DR4 = batch.DR4;
cmd.num_cliprects = batch.num_cliprects;
cmd.cliprects = batch.cliprects;
if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd,
sizeof(cmd))) {
fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
}
age_intel(intel, intel->sarea->last_enqueue);
/* FIXME: use hardware contexts to avoid 'losing' hardware after
* each buffer flush.
*/
intel->vtbl.lost_hardware( intel );
}
if (refill)
intelRefillBatchLocked( intel, allow_unlock );
}
void intelFlushBatch( intelContextPtr intel, GLboolean refill )
{
if (intel->locked) {
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE );
}
else {
LOCK_HARDWARE(intel);
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE );
UNLOCK_HARDWARE(intel);
}
}
void intelWaitForIdle( intelContextPtr intel )
{
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
intel->vtbl.emit_flush( intel );
intelFlushBatch( intel, GL_TRUE );
/* Use an irq to wait for dma idle -- Need to track lost contexts
* to shortcircuit consecutive calls to this function:
*/
intelWaitIrq( intel, intel->alloc.irq_emitted );
intel->alloc.irq_emitted = 0;
}
void intelFlush( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
if (intel->Fallback)
_swrast_flush( ctx );
INTEL_FIREVERTICES( intel );
if (intel->batch.size != intel->batch.space)
intelFlushBatch( intel, GL_FALSE );
}
void intelFinish( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
intelFlush( ctx );
intelWaitForIdle( intel );
}
void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch)
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
GLbitfield tri_mask = 0;
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Take care of cliprects, which are handled differently for
* clears, etc.
*/
intelFlush( &intel->ctx );
if (mask & BUFFER_BIT_FRONT_LEFT) {
if (colorMask == ~0) {
blit_mask |= BUFFER_BIT_FRONT_LEFT;
}
else {
tri_mask |= BUFFER_BIT_FRONT_LEFT;
}
}
if (mask & BUFFER_BIT_BACK_LEFT) {
if (colorMask == ~0) {
blit_mask |= BUFFER_BIT_BACK_LEFT;
}
else {
tri_mask |= BUFFER_BIT_BACK_LEFT;
}
}
if (mask & BUFFER_BIT_DEPTH) {
blit_mask |= BUFFER_BIT_DEPTH;
}
if (mask & BUFFER_BIT_STENCIL) {
if (!intel->hw_stencil) {
swrast_mask |= BUFFER_BIT_STENCIL;
}
else if (ctx->Stencil.WriteMask[0] != 0xff) {
tri_mask |= BUFFER_BIT_STENCIL;
}
else {
blit_mask |= BUFFER_BIT_STENCIL;
}
}
swrast_mask |= (mask & BUFFER_BIT_ACCUM);
if (blit_mask)
intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
if (tri_mask)
intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch);
if (swrast_mask)
_swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
}
void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
{
int region_offset = 0;
drmI830MemAlloc alloc;
int ret;
if (0)
fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size);
alloc.region = I830_MEM_REGION_AGP;
alloc.alignment = 0;
alloc.size = size;
alloc.region_offset = &region_offset;
LOCK_HARDWARE(intel);
/* Make sure the global heap is initialized
*/
if (intel->texture_heaps[0])
driAgeTextures( intel->texture_heaps[0] );
ret = drmCommandWriteRead( intel->driFd,
DRM_I830_ALLOC,
&alloc, sizeof(alloc));
if (ret) {
fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE(intel);
return NULL;
}
if (0)
fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size);
/* Need to propogate this information (agp memory in use) to our
* local texture lru. The kernel has already updated the global
* lru. An alternative would have been to allocate memory the
* usual way and then notify the kernel to pin the allocation.
*/
if (intel->texture_heaps[0])
driAgeTextures( intel->texture_heaps[0] );
UNLOCK_HARDWARE(intel);
return (void *)((char *)intel->intelScreen->tex.map + region_offset);
}
void intelFreeAGP( intelContextPtr intel, void *pointer )
{
int region_offset;
drmI830MemFree memfree;
int ret;
region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
if (region_offset < 0 ||
region_offset > intel->intelScreen->tex.size) {
fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
intel->intelScreen->tex.size);
return;
}
memfree.region = I830_MEM_REGION_AGP;
memfree.region_offset = region_offset;
ret = drmCommandWrite( intel->driFd,
DRM_I830_FREE,
&memfree, sizeof(memfree));
if (ret)
fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret);
}
/* This version of AllocateMemoryMESA allocates only agp memory, and
* only does so after the point at which the driver has been
* initialized.
*
* Theoretically a valid context isn't required. However, in this
* implementation, it is, as I'm using the hardware lock to protect
* the kernel data structures, and the current context to get the
* device fd.
*/
void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn,
GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority)
{
GET_CURRENT_CONTEXT(ctx);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
writefreq, priority);
if (getenv("INTEL_NO_ALLOC"))
return NULL;
if (!ctx || INTEL_CONTEXT(ctx) == 0)
return NULL;
return intelAllocateAGP( INTEL_CONTEXT(ctx), size );
}
/* Called via glXFreeMemoryMESA() */
void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
if (!ctx || INTEL_CONTEXT(ctx) == 0) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return;
}
intelFreeAGP( INTEL_CONTEXT(ctx), pointer );
}
/* Called via glXGetMemoryOffsetMESA()
*
* Returns offset of pointer from the start of agp aperture.
*/
GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn,
const GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
intelContextPtr intel;
if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) {
fprintf(stderr, "%s: no context\n", __FUNCTION__);
return ~0;
}
if (!intelIsAgpMemory( intel, pointer, 0 ))
return ~0;
return intelAgpOffsetFromVirtual( intel, pointer );
}
GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
GLint size )
{
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
int valid = (size >= 0 &&
offset >= 0 &&
offset + size < intel->intelScreen->tex.size);
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid );
return valid;
}
GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer )
{
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
if (offset < 0 || offset > intel->intelScreen->tex.size)
return ~0;
else
return intel->intelScreen->tex.offset + offset;
}
/* Flip the front & back buffes
*/
void intelPageFlip( const __DRIdrawablePrivate *dPriv )
{
#if 0
intelContextPtr intel;
int tmp, ret;
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (dPriv->pClipRects) {
*(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
intel->sarea->nbox = 1;
}
ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
if (ret) {
fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
UNLOCK_HARDWARE( intel );
batch.start = start_offset;
batch.used = used;
batch.cliprects = intel->pClipRects;
batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
batch.DR1 = 0;
batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |
(((GLuint)intel->drawY) << 16));
if (INTEL_DEBUG & DEBUG_DMA)
fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
__FUNCTION__,
batch.start,
batch.start + batch.used * 4,
batch.DR4, batch.num_cliprects);
#if 1
if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,
sizeof(batch))) {
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
tmp = intel->sarea->last_enqueue;
intelRefillBatchLocked( intel );
UNLOCK_HARDWARE( intel );
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
#endif
/* FIXME: use hardware contexts to avoid 'losing' hardware after
* each buffer flush.
*/
intel->vtbl.lost_hardware( intel );
}

View File

@@ -30,37 +30,13 @@
#include "intel_context.h"
extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock );
void intelWaitIrq( struct intel_context *intel, int seq );
int intelEmitIrqLocked( struct intel_context *intel );
extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch);
extern void intelPageFlip( const __DRIdrawablePrivate *dpriv );
extern void intelWaitForIdle( intelContextPtr intel );
extern void intelFlushBatch( intelContextPtr intel, GLboolean refill );
extern void intelFlushBatchLocked( intelContextPtr intel,
GLboolean ignore_cliprects,
GLboolean refill,
GLboolean allow_unlock);
extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock );
extern void intelFinish( GLcontext *ctx );
extern void intelFlush( GLcontext *ctx );
extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size );
extern void intelFreeAGP( intelContextPtr intel, void *pointer );
extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn,
GLsizei size, GLfloat readfreq,
GLfloat writefreq, GLfloat priority );
extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn,
GLvoid *pointer );
extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer );
extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
GLint size );
extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p );
void intel_batch_ioctl( struct intel_context *intel,
GLuint start_offset,
GLuint used,
GLboolean ignore_cliprects);
#endif

View File

@@ -0,0 +1,296 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "bufmgr.h"
#include "enums.h"
static GLenum target_to_target( GLenum target )
{
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
return GL_TEXTURE_CUBE_MAP_ARB;
default:
return target;
}
}
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint cpp,
GLboolean compressed)
{
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(internal_format),
first_level,
last_level);
mt->target = target_to_target(target);
mt->internal_format = internal_format;
mt->first_level = first_level;
mt->last_level = last_level;
mt->width0 = width0;
mt->height0 = height0;
mt->depth0 = depth0;
mt->cpp = cpp;
mt->compressed = compressed;
mt->refcount = 1;
switch (intel->intelScreen->deviceID) {
case PCI_CHIP_I945_G:
ok = i945_miptree_layout( mt );
break;
case PCI_CHIP_I915_G:
case PCI_CHIP_I915_GM:
ok = i915_miptree_layout( mt );
break;
default:
ok = 0;
break;
}
if (ok)
mt->region = intel_region_alloc( intel,
mt->cpp,
mt->pitch,
mt->total_height );
if (!mt->region) {
free(mt);
return NULL;
}
return mt;
}
void intel_miptree_reference( struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src )
{
src->refcount++;
*dst = src;
}
void intel_miptree_release( struct intel_context *intel,
struct intel_mipmap_tree **mt )
{
if (!*mt)
return;
DBG("%s %d\n", __FUNCTION__, (*mt)->refcount-1);
if (--(*mt)->refcount == 0) {
intel_region_release(intel, &((*mt)->region));
free(*mt);
}
*mt = NULL;
}
/* Can the image be pulled into a unified mipmap tree. This mirrors
* the completeness test in a lot of ways.
*
* Not sure whether I want to pass gl_texture_image here.
*/
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face,
GLuint level )
{
DBG("%s %d %d/%d %d/%d\n", __FUNCTION__,
image->Border,
image->InternalFormat, mt->internal_format,
image->IsCompressed, mt->compressed);
/* Images with borders are never pulled into mipmap trees.
*/
if (image->Border)
return GL_FALSE;
if (image->InternalFormat != mt->internal_format ||
image->IsCompressed != mt->compressed)
return GL_FALSE;
DBG("%s: %d/%d %d/%d %d/%d\n", __FUNCTION__,
image->Width, mt->offset[face][level].width,
image->Height, mt->offset[face][level].height,
image->Depth, mt->offset[face][level].depth);
/* Test image dimensions against the base level image adjusted for
* minification. This will also catch images not present in the
* tree, changed targets, etc.
*/
if (image->Width != mt->offset[face][level].width ||
image->Height != mt->offset[face][level].height ||
image->Depth != mt->offset[face][level].depth)
return GL_FALSE;
DBG("%s: success\n", __FUNCTION__);
return GL_TRUE;
}
GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level)
{
return mt->offset[face][level].offset;
}
GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level)
{
return mt->offset[face][level].depth_image_stride;
}
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d)
{
mt->offset[face][level].offset = (x + y * mt->pitch) * mt->cpp;
mt->offset[face][level].width = w;
mt->offset[face][level].height = h;
mt->offset[face][level].depth = d;
}
GLubyte *intel_miptree_image_map(struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint *row_stride,
GLuint *image_stride)
{
DBG("%s \n", __FUNCTION__);
if (row_stride)
*row_stride = mt->pitch * mt->cpp;
if (image_stride)
*image_stride = mt->offset[face][level].depth_image_stride;
return (intel_region_map(intel, mt->region) +
intel_miptree_image_offset(mt, face, level));
}
void intel_miptree_image_unmap(struct intel_context *intel,
struct intel_mipmap_tree *mt)
{
DBG("%s\n", __FUNCTION__);
intel_region_unmap(intel, mt->region);
}
/* Upload data for a particular image.
*/
void intel_miptree_image_data(struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_pitch,
GLuint src_image_pitch)
{
GLuint depth = dst->offset[face][level].depth;
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level);
GLuint i;
DBG("%s\n", __FUNCTION__);
for (i = 0; i < depth; i++) {
intel_region_data(intel,
dst->region, dst_offset,
0,
0,
src,
src_row_pitch,
0, 0, /* source x,y */
dst->offset[face][level].width,
dst->offset[face][level].height);
dst_offset += dst_image_stride;
src += src_image_pitch;
}
}
/* Copy mipmap image between trees
*/
void intel_miptree_image_copy( struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face, GLuint level,
struct intel_mipmap_tree *src )
{
GLuint width = src->offset[face][level].width;
GLuint height = src->offset[face][level].height;
GLuint depth = src->offset[face][level].depth;
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
GLuint src_offset = intel_miptree_image_offset(src, face, level);
GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level);
GLuint src_image_stride = intel_miptree_depth_image_stride(src, face, level);
GLuint i;
for (i = 0; i < depth; i++) {
intel_region_copy(intel,
dst->region, dst_offset,
0,
0,
src->region, src_offset,
0,
0,
width,
height);
dst_offset += dst_image_stride;
src_offset += src_image_stride;
}
}

View File

@@ -0,0 +1,180 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#ifndef INTEL_MIPMAP_TREE_H
#define INTEL_MIPMAP_TREE_H
#include "intel_regions.h"
/* A layer on top of the intel_regions code which adds:
*
* - Code to size and layout a region to hold a set of mipmaps.
* - Query to determine if a new image fits in an existing tree.
* - More refcounting
* - maybe able to remove refcounting from intel_region?
* - ?
*
* The fixed mipmap layout of intel hardware where one offset
* specifies the position of all images in a mipmap hierachy
* complicates the implementation of GL texture image commands,
* compared to hardware where each image is specified with an
* independent offset.
*
* In an ideal world, each texture object would be associated with a
* single bufmgr buffer or 2d intel_region, and all the images within
* the texture object would slot into the tree as they arrive. The
* reality can be a little messier, as images can arrive from the user
* with sizes that don't fit in the existing tree, or in an order
* where the tree layout cannot be guessed immediately.
*
* This structure encodes an idealized mipmap tree. The GL image
* commands build these where possible, otherwise store the images in
* temporary system buffers.
*/
struct intel_mipmap_offset {
GLuint offset;
GLuint width;
GLuint height;
GLuint depth;
GLuint depth_image_stride;
};
struct intel_mipmap_tree {
/* Effectively the key:
*/
GLenum target;
GLenum internal_format;
GLuint first_level;
GLuint last_level;
GLuint width0, height0, depth0;
GLuint cpp;
GLboolean compressed;
/* Derived from the above:
*/
GLuint pitch;
GLuint depth_pitch; /* per-image on i945? */
GLuint total_height;
struct intel_mipmap_offset offset[MAX_FACES][MAX_TEXTURE_LEVELS];
/* The data is held here:
*/
struct intel_region *region;
/* These are also refcounted:
*/
GLuint refcount;
};
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint cpp,
GLboolean compressed);
void intel_miptree_reference( struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src );
void intel_miptree_release( struct intel_context *intel,
struct intel_mipmap_tree **mt );
/* Check if an image fits an existing mipmap tree layout
*/
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face,
GLuint level );
/* Return a pointer to an image within a tree. Return image stride as
* well.
*/
GLubyte *intel_miptree_image_map( struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint *row_stride,
GLuint *image_stride);
void intel_miptree_image_unmap( struct intel_context *intel,
struct intel_mipmap_tree *mt );
/* Return the linear offset of an image relative to the start of the
* tree:
*/
GLuint intel_miptree_image_offset( struct intel_mipmap_tree *mt,
GLuint face,
GLuint level );
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d);
GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level);
/* Upload an image into a tree
*/
void intel_miptree_image_data(struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_pitch,
GLuint src_image_pitch);
/* Copy an image between two trees
*/
void intel_miptree_image_copy( struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face, GLuint level,
struct intel_mipmap_tree *src );
/* i915_mipmap_tree.c:
*/
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt );
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt );
#endif

View File

@@ -1,109 +1,89 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_pixel.h"
static GLboolean
check_color( const GLcontext *ctx, GLenum type, GLenum format,
const struct gl_pixelstore_attrib *packing,
const void *pixels, GLint sz, GLint pitch )
#if 0
struct intel_client_region *intel_pack_region( struct intel_context *intel,
const struct gl_pixelstore_attrib *pack,
GLenum format,
GLenum type,
GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLuint cpp = intel->intelScreen->cpp;
}
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( (pitch & 63) ||
ctx->_ImageTransferState ||
packing->SwapBytes ||
packing->LsbFirst) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
return GL_FALSE;
}
struct intel_client_region *intel_unpack_region( struct intel_context *intel,
const struct gl_pixelstore_attrib *pack,
GLenum format,
GLenum type,
GLvoid *pixels )
{
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
/* XXX: Need to adjust pixels pointer for unpack->skip pixels/rows
* offsets.
*/
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
cpp == 4 &&
format == GL_BGRA ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
}
void release_client_region( struct intel_context *intel,
struct intel_region *region )
{
}
#endif
GLboolean intel_check_color_per_fragment_ops( const GLcontext *ctx )
{
return !(ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits);
}
#if 0
/* The intel_region struct doesn't really do enough to capture the
* format of the pixels in the region. For now this code assumes that
* the region is a display surface and hence is either ARGB8888 or
* RGB565.
*/
GLboolean intel_check_blit_format( struct intel_region *region,
struct intel_client_region *client_region )
{
if (region->cpp == 4
client_region->cpp == 4 &&
client_region->type == GL_UNSIGNED_INT_8_8_8_8_REV &&
client_region->format == GL_BGRA ) {
return GL_TRUE;
}
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: failed\n", __FUNCTION__);
if (region->cpp == 2 &&
client_region->cpp == 2 &&
client_region->type == GL_UNSIGNED_INT_5_6_5_REV &&
client_region->format == GL_BGR ) {
return GL_TRUE;
}
fprintf(stderr, "%s: request doesn't match pixel format\n", __FUNCTION__);
return GL_FALSE;
}
#endif
static GLboolean
check_color_per_fragment_ops( const GLcontext *ctx )
GLboolean intel_clip_to_framebuffer( GLcontext *ctx,
const GLframebuffer *buffer,
GLint *x, GLint *y,
GLsizei *width, GLsizei *height )
{
int result;
result = (!( ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits
) &&
ctx->Current.RasterPosValid);
return result;
}
static GLboolean
clip_pixelrect( const GLcontext *ctx,
const GLframebuffer *buffer,
GLint *x, GLint *y,
GLsizei *width, GLsizei *height,
GLint *size )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
/* left clipping */
if (*x < buffer->_Xmin) {
*width -= (buffer->_Xmin - *x);
@@ -130,343 +110,9 @@ clip_pixelrect( const GLcontext *ctx,
if (*height <= 0)
return GL_FALSE;
*size = ((*y + *height - 1) * intel->intelScreen->front.pitch +
(*x + *width - 1) * intel->intelScreen->cpp);
return GL_TRUE;
}
static GLboolean
intelTryReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLint size = 0;
GLint pitch = pack->RowLength ? pack->RowLength : width;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
/* Only accelerate reading to agp buffers.
*/
if ( !intelIsAgpMemory(intel, pixels,
pitch * height * intel->intelScreen->cpp ) ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
return GL_FALSE;
}
/* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
* blitter:
*/
if (!pack->Invert) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, pack, pixels, size, pitch))
return GL_FALSE;
switch ( intel->intelScreen->cpp ) {
case 4:
break;
default:
return GL_FALSE;
}
/* Although the blits go on the command buffer, need to do this and
* fire with lock held to guarentee cliprects and drawOffset are
* correct.
*
* This is an unusual situation however, as the code which flushes
* a full command buffer expects to be called unlocked. As a
* workaround, immediately flush the buffer on aquiring the lock.
*/
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
int src_offset = intel->drawOffset;
int src_pitch = intel->intelScreen->front.pitch;
int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
drm_clip_rect_t *box = dPriv->pClipRects;
int i;
if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( intel );
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s totally clipped -- nothing to do\n",
__FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
src_pitch, pitch);
for (i = 0 ; i < nbox ; i++)
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlitLocked( intel,
intel->intelScreen->cpp,
src_pitch, src_offset,
pitch, dst_offset,
bx, by,
bx - x, by - y,
bw, bh );
}
}
UNLOCK_HARDWARE( intel );
intelFinish( &intel->ctx );
return GL_TRUE;
}
static void
intelReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,
pixels))
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,
pixels);
}
static void do_draw_pix( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint pitch,
const void *pixels,
GLuint dest )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = intel->driDrawable;
drm_clip_rect_t *box = dPriv->pClipRects;
int nbox = dPriv->numClipRects;
int i;
int size;
int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
int src_pitch = pitch;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (ctx->DrawBuffer)
{
y -= height; /* cope with pixel zoom */
if (!clip_pixelrect(ctx, ctx->DrawBuffer,
&x, &y, &width, &height,
&size)) {
UNLOCK_HARDWARE( intel );
return;
}
y = dPriv->h - y - height; /* convert from gl to hardware coords */
x += dPriv->x;
y += dPriv->y;
for (i = 0 ; i < nbox ; i++ )
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlitLocked( intel,
intel->intelScreen->cpp,
src_pitch, src_offset,
intel->intelScreen->front.pitch,
intel->drawOffset,
bx - x, by - y,
bx, by,
bw, bh );
}
}
UNLOCK_HARDWARE( intel );
intelFinish( &intel->ctx );
}
static GLboolean
intelTryDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
GLuint dest;
GLuint cpp = intel->intelScreen->cpp;
GLint size = width * pitch * cpp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
switch (format) {
case GL_RGB:
case GL_RGBA:
case GL_BGRA:
dest = intel->drawOffset;
/* Planemask doesn't have full support in blits.
*/
if (!ctx->Color.ColorMask[RCOMP] ||
!ctx->Color.ColorMask[GCOMP] ||
!ctx->Color.ColorMask[BCOMP] ||
!ctx->Color.ColorMask[ACOMP]) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: planemask\n", __FUNCTION__);
return GL_FALSE;
}
/* Can't do conversions on agp reads/draws.
*/
if ( !intelIsAgpMemory( intel, pixels, size ) ) {
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s: not agp memory\n", __FUNCTION__);
return GL_FALSE;
}
if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
return GL_FALSE;
}
if (!check_color_per_fragment_ops(ctx)) {
return GL_FALSE;
}
if (ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != -1.0F)
return GL_FALSE;
break;
default:
return GL_FALSE;
}
if ( intelIsAgpMemory(intel, pixels, size) )
{
do_draw_pix( ctx, x, y, width, height, pitch, pixels,
dest );
return GL_TRUE;
}
else if (0)
{
/* Pixels is in regular memory -- get dma buffers and perform
* upload through them. No point doing this for regular uploads
* but once we remove some of the restrictions above (colormask,
* pixelformat conversion, zoom?, etc), this could be a win.
*/
}
else
return GL_FALSE;
}
static void
intelDrawPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!intelTryDrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
}
/**
* Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
* for the color buffer. Don't support zooming, pixel transfer, etc.
* We do support copying from one window to another, ala glXMakeCurrentRead.
*/
static void
intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy, GLsizei width, GLsizei height,
GLint destx, GLint desty, GLenum type )
{
#if 0
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
const SWcontext *swrast = SWRAST_CONTEXT( ctx );
XMesaDisplay *dpy = xmesa->xm_visual->display;
const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
const XMesaGC gc = xmesa->xm_draw_buffer->gc;
ASSERT(dpy);
ASSERT(gc);
if (drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
readBuffer &&
type == GL_COLOR &&
(swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
ctx->Pixel.ZoomX == 1.0 && /* no zooming */
ctx->Pixel.ZoomY == 1.0) {
/* Note: we don't do any special clipping work here. We could,
* but X will do it for us.
*/
srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
XCopyArea(dpy, readBuffer, drawBuffer, gc,
srcx, srcy, width, height, destx, desty);
}
#else
_swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
#endif
}
@@ -476,14 +122,16 @@ void intelInitPixelFuncs( struct dd_function_table *functions )
*/
functions->Accum = _swrast_Accum;
functions->Bitmap = _swrast_Bitmap;
functions->CopyPixels = intelCopyPixels;
if (!getenv("INTEL_NO_BLITS")) {
if (getenv("INTEL_NO_BLITS") == 0) {
functions->CopyPixels = intelCopyPixels;
functions->ReadPixels = intelReadPixels;
functions->DrawPixels = intelDrawPixels;
}
else {
functions->CopyPixels = _swrast_CopyPixels;
functions->ReadPixels = _swrast_ReadPixels;
functions->DrawPixels = _swrast_DrawPixels;
}
}

View File

@@ -0,0 +1,63 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#ifndef INTEL_PIXEL_H
#define INTEL_PIXEL_H
#include "mtypes.h"
void intelInitPixelFuncs( struct dd_function_table *functions );
GLboolean intel_check_color_per_fragment_ops( const GLcontext *ctx );
GLboolean intel_clip_to_framebuffer( GLcontext *ctx,
const GLframebuffer *buffer,
GLint *x, GLint *y,
GLsizei *width, GLsizei *height );
void intelReadPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
void intelDrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
void intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty,
GLenum type );
#endif

View File

@@ -0,0 +1,196 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "bufmgr.h"
static GLboolean do_texture_copypixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty,
GLenum type )
{
return GL_FALSE;
}
/**
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
*/
static GLboolean do_blit_copypixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty,
GLenum type )
{
struct intel_context *intel = intel_context( ctx );
struct intel_region *dst = intel_drawbuf_region( intel );
struct intel_region *src = NULL;
/* Copypixels can be more than a straight copy. Ensure all the
* extra operations are disabled:
*/
if (!intel_check_color_per_fragment_ops(ctx) ||
ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != 1.0F)
return GL_FALSE;
switch (type) {
case GL_COLOR:
src = intel_readbuf_region( intel );
break;
case GL_DEPTH:
/* Don't think this is really possible execpt at 16bpp, when we have no stencil.
*/
if (intel->intelScreen->cpp == 2)
src = intel->depth_region;
break;
case GL_STENCIL:
/* Don't think this is really possible.
*/
break;
case GL_DEPTH_STENCIL_EXT:
/* Does it matter whether it is stencil/depth or depth/stencil?
*/
src = intel->depth_region;
break;
default:
break;
}
if (!src || !dst)
return GL_FALSE;
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
drm_clip_rect_t *box = dPriv->pClipRects;
GLint nbox = dPriv->numClipRects;
GLint delta_x = srcx - dstx;
GLint delta_y = srcy - dsty;
GLuint i;
if (!intel_clip_to_framebuffer(ctx, ctx->DrawBuffer, &dstx, &dsty, &width, &height))
goto out;
/* Update source for clipped dest. Need to also clip the source rect.
*/
srcx = dstx + delta_x;
srcy = dsty + delta_y;
if (!intel_clip_to_framebuffer(ctx, ctx->DrawBuffer, &srcx, &srcy, &width, &height))
goto out;
/* Update dest for clipped source:
*/
dstx = srcx - delta_x;
dsty = srcy - delta_y;
srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
dsty = dPriv->h - dsty - height; /* convert from gl to hardware coords */
srcx += dPriv->x;
dstx += dPriv->x;
srcy += dPriv->y;
dsty += dPriv->y;
/* Could do slightly more clipping: Eg, take the intersection of
* the existing set of cliprects and those cliprects translated
* by delta_x, delta_y:
*
* This code will not overwrite other windows, but will
* introduce garbage when copying from obscured window regions.
*/
for (i = 0 ; i < nbox ; i++ )
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < dstx) bw -= dstx - bx, bx = dstx;
if (by < dsty) bh -= dsty - by, by = dsty;
if (bx + bw > dstx + width) bw = dstx + width - bx;
if (by + bh > dsty + height) bh = dsty + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlit( intel,
dst->cpp,
src->pitch, src->buffer, 0,
dst->pitch, dst->buffer, 0,
bx + delta_x, by - delta_y, /* srcx, srcy */
bx, by, /* dstx, dsty */
bw, bh );
}
}
out:
intel_batchbuffer_flush( intel->batch );
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
void intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty,
GLenum type )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
return;
if (do_texture_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
return;
_mesa_printf("fallback to _swrast_CopyPixels\n");
_swrast_CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type);
}

View File

@@ -0,0 +1,242 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "bufmgr.h"
static GLboolean do_texture_draw_pixels( struct intel_context *intel,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
#if 0
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int textureFormat;
GLenum glTextureFormat;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( ctx->_ImageTransferState ||
unpack->SwapBytes ||
unpack->LsbFirst ||
ctx->Texture._EnabledUnits ||
ctx->FragmentProgram._Enabled) {
fprintf(stderr, "%s: cannot use texture path\n", __FUNCTION__);
return GL_FALSE;
}
glGenTextures();
glTextureImage2D();
glBindTexture();
glEnable(GL_TEXTURE_RECTANGLE_NV);
glDisable(GL_POLYGON_STIPPLE);
glDisable(GL_CULL);
_mesa_install_vp_passthrough(ctx);
_mesa_push_current(ctx);
if (intel->Fallback)
goto Fail;
glBegin(GL_QUADS);
glVertex3f();
glTexCoord2f();
glVertex3f();
glTexCoord2f();
glVertex3f();
glTexCoord2f();
glVertex3f();
glTexCoord2f();
glEnd();
glFinish();
ASSIGN_4V(ctx->Current.Atrrib[VERT_ATTRIB_TEX0], tex0);
fail:
glDisable(GL_TEXTURE_RECTANGLE_NV);
glDeleteTextures();
glBindTexture(old);
#endif
return GL_FALSE;
}
/* Pros:
* - no waiting for idle before updating framebuffer.
*
* Cons:
* - if upload is by memcpy, this may actually be slower than fallback path.
* - uploads the whole image even if destination is clipped
*
* Need to benchmark.
*/
static GLboolean do_blit_draw_pixels( struct intel_context *intel,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
#if 0
struct intel_region *dest = intel_drawbuf_region(intel);
struct intel_region *src = NULL;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!src || !dest)
return GL_FALSE;
if (!intel_check_blit_format(dest, src))
return GL_FALSE;
if (!intel_check_blit_fragment_ops(ctx))
return GL_FALSE;
if (ctx->Pixel.ZoomX != 1.0F)
return GL_FALSE;
if (ctx->Pixel.ZoomY == -1.0F)
y -= height;
else if (ctx->Pixel.ZoomY == 1.0F) {
src_pitch = -src_pitch;
src_y += height;
}
else
return GL_FALSE;
if (unpack->BufferObj->Name) {
src = intel_bufferobj_unpack_region(intel, unpack,
width, height,
format, type,
unpack->BufferObj);
src_offset = (unsigned long)pixels;
}
else {
src = intel_client_unpack_region(intel, unpack,
width, height,
format, type, pixels);
src_offset = 0;
}
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *box = dPriv->pClipRects;
drm_clip_rect_t rect;
int i;
y = dPriv->h - y - height; /* convert from gl to hardware coords */
x += dPriv->x;
y += dPriv->y;
for (i = 0 ; i < nbox ; i++ )
{
if (!intel_intersect_cliprects(rect, db_rect, &box[i]))
continue;
intelEmitCopyBlit( intel,
intel->intelScreen->cpp,
src->pitch, src->buffer, src_offset,
dst->pitch, dst->buffer, 0,
rect->x1 - x,
rect->y1 - y,
rect->x1,
rect->y1,
rect->x2 - rect->x1,
rect->y2 - rect->y1 );
}
}
intel_release_unpack_region( intel, src );
fence = intel_batchbuffer_flush( intel->batch );
UNLOCK_HARDWARE( intel );
bmWaitFence(intel->bm, fence);
intel_region_release(intel, &src);
#endif
return GL_FALSE;
}
void intelDrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
struct intel_context *intel = intel_context(ctx);
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (do_texture_draw_pixels( intel, x, y, width, height, format, type,
unpack, pixels ))
return;
if (do_blit_draw_pixels( intel, x, y, width, height, format, type,
unpack, pixels ))
return;
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
}

View File

@@ -0,0 +1,249 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "bufmgr.h"
static GLboolean
do_texture_readpixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
struct intel_region *dest_region )
{
#if 0
struct intel_context *intel = intel_context(ctx);
intelScreenPrivate *screen = intel->intelScreen;
GLint pitch = pack->RowLength ? pack->RowLength : width;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int textureFormat;
GLenum glTextureFormat;
int destFormat, depthFormat, destPitch;
drm_clip_rect_t tmp;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if ( ctx->_ImageTransferState ||
pack->SwapBytes ||
pack->LsbFirst ||
!pack->Invert) {
fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
return GL_FALSE;
}
intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel));
if (!intel->vtbl.meta_render_dest(intel,
dest_region,
type, format))
{
fprintf(stderr, "%s: couldn't set dest %s/%s\n",
__FUNCTION__,
_mesa_lookup_enum_by_nr(type),
_mesa_lookup_enum_by_nr(format));
return GL_FALSE;
}
LOCK_HARDWARE( intel );
intel->vtbl.install_meta_state(intel);
intel->vtbl.meta_no_depth_stencil_write(intel);
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
UNLOCK_HARDWARE( intel );
SET_STATE(i830, state);
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
return GL_TRUE;
}
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
/* Set the frontbuffer up as a large rectangular texture.
*/
intel->vtbl.meta_tex_rect_source( intel,
src_region,
textureFormat );
intel->vtbl.meta_texture_blend_replace( i830, glTextureFormat );
/* Set the 3d engine to draw into the destination region:
*/
intel->vtbl.meta_draw_region(intel, dest_region);
intel->vtbl.meta_draw_format(intel, destFormat, depthFormat ); /* ?? */
/* Draw a single quad, no cliprects:
*/
intel->vtbl.meta_disable_cliprects(intel);
intel->vtbl.draw_quad(intel,
0, width, 0, height,
0x00ff00ff,
x, x+width,
y, y+height );
intel->vtbl.leave_meta_state(intel);
UNLOCK_HARDWARE( intel );
intel_region_wait_fence( ctx, dest_region ); /* required by GL */
return GL_TRUE;
#endif
return GL_FALSE;
}
static GLboolean do_blit_readpixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
#if 0
struct intel_context *intel = intel_context(ctx);
GLint pitch = pack->RowLength ? pack->RowLength : width;
struct intel_region *src = intel_readbuf_region(intel);
struct intel_client_region *dst = intel_client_pack_region(intel,
pack,
pixels);
if (ctx->_ImageTransferState ||
pack->SwapBytes ||
pack->LsbFirst) {
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
return GL_FALSE;
}
/* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
* blitter:
*/
if (!pack->Invert) {
fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
return GL_FALSE;
}
if (!intel_check_blit_format(src, format, type))
return GL_FALSE;
/* Although the blits go on the command buffer, need to do this and
* fire with lock held to guarentee cliprects are correct.
*/
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *box = dPriv->pClipRects;
int i;
y = dPriv->h - y - height;
x += dPriv->x;
y += dPriv->y;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
src_pitch, pitch);
for (i = 0 ; i < nbox ; i++)
{
GLint bx = box[i].x1;
GLint by = box[i].y1;
GLint bw = box[i].x2 - bx;
GLint bh = box[i].y2 - by;
if (bx < x) bw -= x - bx, bx = x;
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
if (bw <= 0) continue;
if (bh <= 0) continue;
intelEmitCopyBlit( intel,
src->cpp,
src->pitch, src->buffer, 0,
dst->pitch, dst->buffer, 0,
bx, by,
bx - x, by - y,
bw, bh );
}
intel_batchbuffer_flush(intel->batch);
intel_client_region_release(intel, dst);
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
#endif
return GL_FALSE;
}
void
intelReadPixels( GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
intelFlush( ctx );
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
return;
if (do_texture_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
return;
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels);
}

View File

@@ -0,0 +1,269 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
/* Provide additional functionality on top of bufmgr buffers:
* - 2d semantics and blit operations
* - refcounting of buffers for multiple images in a buffer.
* - refcounting of buffer mappings.
* - some logic for moving the buffers to the best memory pools for
* given operations.
*
* Most of this is to make it easier to implement the fixed-layout
* mipmap tree required by intel hardware in the face of GL's
* programming interface where each image can be specifed in random
* order and it isn't clear what layout the tree should have until the
* last moment.
*/
#include "intel_context.h"
#include "intel_regions.h"
#include "intel_blit.h"
#include "bufmgr.h"
/* XXX: Thread safety?
*/
GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
if (!region->map_refcount++) {
region->map = bmMapBuffer(intel->bm, region->buffer, 0);
}
return region->map;
}
void intel_region_unmap(struct intel_context *intel,
struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
if (!--region->map_refcount) {
bmUnmapBuffer(intel->bm, region->buffer);
region->map = NULL;
}
}
struct intel_region *intel_region_alloc( struct intel_context *intel,
GLuint cpp,
GLuint pitch,
GLuint height )
{
struct intel_region *region = calloc(sizeof(*region), 1);
DBG("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
region->refcount = 1;
bmGenBuffers(intel->bm, 1, &region->buffer);
bmBufferData(intel->bm, region->buffer, pitch * cpp * height, NULL, 0);
return region;
}
void intel_region_reference( struct intel_region **dst,
struct intel_region *src)
{
src->refcount++;
assert(*dst == NULL);
*dst = src;
}
void intel_region_release( struct intel_context *intel,
struct intel_region **region )
{
if (!*region)
return;
DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1);
if (--(*region)->refcount == 0) {
assert((*region)->map_refcount == 0);
bmDeleteBuffers(intel->bm, 1, &(*region)->buffer);
free(*region);
}
*region = NULL;
}
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height )
{
struct intel_region *region = calloc(sizeof(*region), 1);
GLuint size = cpp * pitch * height;
GLint pool;
DBG("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
region->refcount = 1;
/* Recipe for creating a static buffer - create a static pool with
* the right offset and size, generate a buffer and use a special
* call to bind it to all of the memory in that pool.
*/
pool = bmInitPool(intel->bm, offset, virtual, size,
(BM_MEM_AGP |
BM_NO_UPLOAD |
BM_NO_EVICT |
BM_NO_MOVE));
if (pool < 0) {
_mesa_printf("bmInitPool failed for static region\n");
exit(1);
}
bmGenBuffers(intel->bm, 1, &region->buffer);
bmBufferStatic(intel->bm, region->buffer, size, pool);
return region;
}
static void _mesa_copy_rect( GLubyte *dst,
GLuint cpp,
GLuint dst_pitch,
GLuint dst_x,
GLuint dst_y,
GLuint width,
GLuint height,
GLubyte *src,
GLuint src_pitch,
GLuint src_x,
GLuint src_y )
{
GLuint i;
dst_pitch *= cpp;
src_pitch *= cpp;
dst += dst_x * cpp;
src += src_x * cpp;
dst += dst_y * dst_pitch;
src += src_y * dst_pitch;
width *= cpp;
if (width == dst_pitch &&
width == src_pitch)
memcpy(dst, src, height * width);
else {
for (i = 0; i < height; i++) {
memcpy(dst, src, width);
dst += dst_pitch;
src += src_pitch;
}
}
}
/* Upload data to a rectangular sub-region. Lots of choices how to do this:
*
* - memcpy by span to current destination
* - upload data as new buffer and blit
*
* Currently always memcpy.
*/
void intel_region_data(struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
void *src, GLuint src_pitch,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height)
{
DBG("%s\n", __FUNCTION__);
LOCK_HARDWARE(intel);
_mesa_copy_rect(intel_region_map(intel, dst) + dst_offset,
dst->cpp,
dst->pitch,
dstx, dsty,
width, height,
src,
src_pitch,
srcx, srcy);
intel_region_unmap(intel, dst);
UNLOCK_HARDWARE(intel);
}
/* Copy rectangular sub-regions. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
void intel_region_copy( struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
struct intel_region *src,
GLuint src_offset,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height )
{
DBG("%s\n", __FUNCTION__);
assert(src->cpp == dst->cpp);
intelEmitCopyBlit(intel,
dst->cpp,
src->pitch, src->buffer, src_offset,
dst->pitch, dst->buffer, dst_offset,
srcx, srcy,
dstx, dsty,
width, height);
}
/* Fill a rectangular sub-region. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
void intel_region_fill( struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
GLuint width, GLuint height,
GLuint color )
{
DBG("%s\n", __FUNCTION__);
intelEmitFillBlit(intel,
dst->cpp,
dst->pitch, dst->buffer, dst_offset,
dstx, dsty,
width, height,
color );
}

View File

@@ -0,0 +1,115 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#ifndef INTEL_REGIONS_H
#define INTEL_REGIONS_H
#include "mtypes.h"
#include "bufmgr.h" /* for DBG! */
struct intel_context;
/* A layer on top of the bufmgr buffers that adds a few useful things:
*
* - Refcounting for local buffer references.
* - Refcounting for buffer maps
* - Buffer dimensions - pitch and height.
* - Blitter commands for copying 2D regions between buffers.
*/
struct intel_region {
GLuint buffer;
GLuint refcount;
GLuint cpp;
GLuint pitch;
GLuint height;
GLubyte *map;
GLuint map_refcount;
};
/* Allocate a refcounted region. Pointers to regions should only be
* copied by calling intel_reference_region().
*/
struct intel_region *intel_region_alloc( struct intel_context *intel,
GLuint cpp,
GLuint pitch,
GLuint height );
void intel_region_reference( struct intel_region **dst,
struct intel_region *src );
void intel_region_release(struct intel_context *intel,
struct intel_region **ib );
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height );
/* Map/unmap regions. This is refcounted also:
*/
GLubyte *intel_region_map(struct intel_context *intel,
struct intel_region *ib);
void intel_region_unmap(struct intel_context *intel,
struct intel_region *ib);
/* Upload data to a rectangular sub-region
*/
void intel_region_data(struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
void *src, GLuint src_stride,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height);
/* Copy rectangular sub-regions
*/
void intel_region_copy( struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
struct intel_region *src,
GLuint src_offset,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height );
/* Fill a rectangular sub-region
*/
void intel_region_fill( struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
GLuint width, GLuint height,
GLuint color );
#endif

View File

@@ -106,7 +106,7 @@ static const int scale_prim[GL_POLYGON+1] = {
};
static void intelDmaPrimitive( intelContextPtr intel, GLenum prim )
static void intelDmaPrimitive( struct intel_context *intel, GLenum prim )
{
if (0) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
INTEL_FIREVERTICES(intel);
@@ -115,7 +115,7 @@ static void intelDmaPrimitive( intelContextPtr intel, GLenum prim )
}
#define LOCAL_VARS intelContextPtr intel = INTEL_CONTEXT(ctx)
#define LOCAL_VARS struct intel_context *intel = intel_context(ctx)
#define INIT( prim ) \
do { \
intelDmaPrimitive( intel, prim ); \
@@ -142,7 +142,7 @@ do { \
/* Heuristic to choose between the two render paths:
*/
static GLboolean choose_render( intelContextPtr intel,
static GLboolean choose_render( struct intel_context *intel,
struct vertex_buffer *VB )
{
int vertsz = intel->vertex_size;
@@ -194,11 +194,15 @@ static GLboolean choose_render( intelContextPtr intel,
static GLboolean intel_run_render( GLcontext *ctx,
struct tnl_pipeline_stage *stage )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i;
/* disabled
*/
return GL_TRUE;
/* Don't handle clipping or indexed vertices.
*/
if (intel->RenderIndex != 0 ||

View File

@@ -104,14 +104,14 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
intelScreen->cpp = gDRIPriv->cpp;
switch (gDRIPriv->bitsPerPixel) {
case 15: intelScreen->fbFormat = DV_PF_555; break;
case 16: intelScreen->fbFormat = DV_PF_565; break;
case 32: intelScreen->fbFormat = DV_PF_8888; break;
default: exit(1); break;
}
intelScreen->front.pitch = gDRIPriv->fbStride;
intelScreen->front.offset = gDRIPriv->fbOffset;
intelScreen->front.map = sPriv->pFB;
intelScreen->front.map = (char *)sPriv->pFB;
intelScreen->back.offset = gDRIPriv->backOffset;
intelScreen->back.pitch = gDRIPriv->backPitch;
@@ -166,7 +166,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
if (1) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
intelScreen->drmMinor = sPriv->drmMinor;
@@ -202,13 +202,8 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
if (glx_enable_extension != NULL) {
(*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
(*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
}
sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
sPriv->psc->freeMemory = (void *) intelFreeMemoryMESA;
sPriv->psc->memoryOffset = (void *) intelGetMemoryOffsetMESA;
return GL_TRUE;
}
@@ -338,12 +333,16 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
switch (intelScreen->deviceID) {
#if 0
/* Don't deal with i830 until texture work complete:
*/
case PCI_CHIP_845_G:
case PCI_CHIP_I830_M:
case PCI_CHIP_I855_GM:
case PCI_CHIP_I865_G:
return i830CreateContext( mesaVis, driContextPriv,
sharedContextPrivate );
#endif
case PCI_CHIP_I915_G:
case PCI_CHIP_I915_GM:

View File

@@ -32,6 +32,9 @@
#include "dri_util.h"
#include "xmlconfig.h"
/* XXX: change name or eliminate to avoid conflict with "struct
* intel_region"!!!
*/
typedef struct {
drm_handle_t handle;
drmSize size; /* region size in bytes */

View File

@@ -31,16 +31,18 @@
#include "colormac.h"
#include "intel_screen.h"
#include "intel_span.h"
#include "intel_regions.h"
#include "intel_ioctl.h"
#include "intel_tex.h"
#include "swrast/swrast.h"
#undef DBG
#define DBG 0
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
struct intel_context *intel = intel_context(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
driRenderbuffer *drb = (driRenderbuffer *) rb; \
GLuint pitch = drb->pitch * drb->cpp; \
@@ -52,7 +54,7 @@
(void) buf; (void) p
#define LOCAL_DEPTH_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
struct intel_context *intel = intel_context(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
driRenderbuffer *drb = (driRenderbuffer *) rb; \
GLuint pitch = drb->pitch * drb->cpp; \
@@ -93,27 +95,6 @@ do { \
#define TAG(x) intel##x##_565
#include "spantmp.h"
/* 15 bit, 555 rgb color spanline and pixel functions
*/
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = (((r & 0xf8) << 7) | \
((g & 0xf8) << 3) | \
((b & 0xf8) >> 3))
#define WRITE_PIXEL( _x, _y, p ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = p
#define READ_RGBA( rgba, _x, _y ) \
do { \
GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \
rgba[0] = (p >> 7) & 0xf8; \
rgba[1] = (p >> 3) & 0xf8; \
rgba[2] = (p << 3) & 0xf8; \
rgba[3] = 255; \
} while(0)
#define TAG(x) intel##x##_555
#include "spantmp.h"
/* 16 bit depthbuffer functions.
*/
@@ -130,7 +111,7 @@ do { \
#undef LOCAL_VARS
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
struct intel_context *intel = intel_context(ctx); \
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
driRenderbuffer *drb = (driRenderbuffer *) rb; \
GLuint pitch = drb->pitch * drb->cpp; \
@@ -204,17 +185,47 @@ do { \
*/
void intelSpanRenderStart( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
GLuint i;
intelFlush(&intel->ctx);
LOCK_HARDWARE(intel);
intelWaitForIdle(intel);
/* Just map the framebuffer and all textures. Bufmgr code will
* take care of waiting on the necessary fences:
*/
intel_region_map(intel, intel->front_region);
intel_region_map(intel, intel->back_region);
intel_region_map(intel, intel->depth_region);
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
intel_tex_map_images(intel, intel_texture_object(texObj));
}
}
}
void intelSpanRenderFinish( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
struct intel_context *intel = intel_context( ctx );
GLuint i;
_swrast_flush( ctx );
/* Now unmap the framebuffer:
*/
intel_region_unmap(intel, intel->front_region);
intel_region_unmap(intel, intel->back_region);
intel_region_unmap(intel, intel->depth_region);
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
intel_tex_unmap_images(intel, intel_texture_object(texObj));
}
}
UNLOCK_HARDWARE( intel );
}
@@ -233,10 +244,7 @@ void
intelSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
{
if (drb->Base.InternalFormat == GL_RGBA) {
if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) {
intelInitPointers_555(&drb->Base);
}
else if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
intelInitPointers_565(&drb->Base);
}
else {

View File

@@ -30,10 +30,12 @@
#include "context.h"
#include "macros.h"
#include "enums.h"
#include "colormac.h"
#include "dd.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_regions.h"
#include "swrast/swrast.h"
int intel_translate_compare_func( GLenum func )
@@ -164,70 +166,26 @@ int intel_translate_logic_op( GLenum opcode )
}
}
static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
intelScreenPrivate *screen = intel->intelScreen;
int front = 0;
if (!ctx->DrawBuffer)
return;
switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
case BUFFER_BIT_FRONT_LEFT:
front = 1;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
case BUFFER_BIT_BACK_LEFT:
front = 0;
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
break;
default:
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
return;
}
if ( intel->sarea->pf_current_page == 1 )
front ^= 1;
intelSetFrontClipRects( intel );
if (front) {
intel->drawOffset = screen->front.offset;
} else {
intel->drawOffset = screen->back.offset;
}
intel->vtbl.set_draw_offset( intel, intel->drawOffset );
}
static void intelReadBuffer( GLcontext *ctx, GLenum mode )
{
/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
}
static void intelClearColor(GLcontext *ctx, const GLfloat color[4])
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
intelScreenPrivate *screen = intel->intelScreen;
GLubyte clear_chan[4];
CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]);
CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]);
UNCLAMPED_FLOAT_TO_RGBA_CHAN(clear_chan, color);
intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat,
intel->clear_red,
intel->clear_green,
intel->clear_blue,
intel->clear_alpha);
clear_chan[0],
clear_chan[1],
clear_chan[2],
clear_chan[3]);
}
static void intelCalcViewport( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
const GLfloat *v = ctx->Viewport._WindowMap.m;
GLfloat *m = intel->ViewportMatrix.m;
GLint h = 0;
@@ -263,18 +221,111 @@ static void intelDepthRange( GLcontext *ctx,
*/
static void intelRenderMode( GLcontext *ctx, GLenum mode )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
}
void intelInitStateFuncs( struct dd_function_table *functions )
{
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
functions->RenderMode = intelRenderMode;
functions->Viewport = intelViewport;
functions->DepthRange = intelDepthRange;
functions->ClearColor = intelClearColor;
}
void intelInitState( GLcontext *ctx )
{
/* Mesa should do this for us:
*/
ctx->Driver.AlphaFunc( ctx,
ctx->Color.AlphaFunc,
ctx->Color.AlphaRef);
ctx->Driver.BlendColor( ctx,
ctx->Color.BlendColor );
ctx->Driver.BlendEquationSeparate( ctx,
ctx->Color.BlendEquationRGB,
ctx->Color.BlendEquationA);
ctx->Driver.BlendFuncSeparate( ctx,
ctx->Color.BlendSrcRGB,
ctx->Color.BlendDstRGB,
ctx->Color.BlendSrcA,
ctx->Color.BlendDstA);
ctx->Driver.ColorMask( ctx,
ctx->Color.ColorMask[RCOMP],
ctx->Color.ColorMask[GCOMP],
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP]);
ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
ctx->Driver.DepthFunc( ctx, ctx->Depth.Func );
ctx->Driver.DepthMask( ctx, ctx->Depth.Mask );
ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag );
ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled );
ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled );
ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE );
ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
{
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
}
ctx->Driver.LineWidth( ctx, ctx->Line.Width );
ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp );
ctx->Driver.PointSize( ctx, ctx->Point.Size );
ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple );
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel );
ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT,
ctx->Stencil.Function[0],
ctx->Stencil.Ref[0],
ctx->Stencil.ValueMask[0] );
ctx->Driver.StencilFuncSeparate( ctx, GL_BACK,
ctx->Stencil.Function[1],
ctx->Stencil.Ref[1],
ctx->Stencil.ValueMask[1] );
ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
ctx->Driver.StencilOpSeparate( ctx, GL_FRONT,
ctx->Stencil.FailFunc[0],
ctx->Stencil.ZFailFunc[0],
ctx->Stencil.ZPassFunc[0]);
ctx->Driver.StencilOpSeparate( ctx, GL_BACK,
ctx->Stencil.FailFunc[1],
ctx->Stencil.ZFailFunc[1],
ctx->Stencil.ZPassFunc[1]);
ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
}

View File

@@ -1,830 +1,162 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "macros.h"
#include "simple_list.h"
#include "enums.h"
#include "image.h"
#include "texstore.h"
#include "texformat.h"
#include "teximage.h"
#include "texmem.h"
#include "texobj.h"
#include "swrast/swrast.h"
#include "mm.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_ioctl.h"
static GLboolean
intelValidateClientStorage( intelContextPtr intel, GLenum target,
GLint internalFormat,
GLint srcWidth, GLint srcHeight,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
static GLboolean intelIsTextureResident(GLcontext *ctx,
struct gl_texture_object *texObj)
{
GLcontext *ctx = &intel->ctx;
int texelBytes;
if (0)
fprintf(stderr, "intformat %s format %s type %s\n",
_mesa_lookup_enum_by_nr( internalFormat ),
_mesa_lookup_enum_by_nr( format ),
_mesa_lookup_enum_by_nr( type ));
if (!ctx->Unpack.ClientStorage)
return 0;
if (ctx->_ImageTransferState ||
texImage->IsCompressed ||
texObj->GenerateMipmap)
return 0;
/* This list is incomplete
*/
switch ( internalFormat ) {
case GL_RGBA:
if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
texImage->TexFormat = &_mesa_texformat_argb8888;
texelBytes = 4;
}
else
return 0;
break;
case GL_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
texImage->TexFormat = &_mesa_texformat_rgb565;
texelBytes = 2;
}
else
return 0;
break;
case GL_YCBCR_MESA:
if ( format == GL_YCBCR_MESA &&
type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
texelBytes = 2;
}
else if ( format == GL_YCBCR_MESA &&
(type == GL_UNSIGNED_SHORT_8_8_APPLE ||
type == GL_UNSIGNED_BYTE)) {
texImage->TexFormat = &_mesa_texformat_ycbcr;
texelBytes = 2;
}
else
return 0;
break;
default:
return 0;
}
/* Could deal with these packing issues, but currently don't:
*/
if (packing->SkipPixels ||
packing->SkipRows ||
packing->SwapBytes ||
packing->LsbFirst) {
return 0;
}
{
GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
format, type);
if (0)
fprintf(stderr, "%s: srcRowStride %d/%x\n",
__FUNCTION__, srcRowStride, srcRowStride);
/* Could check this later in upload, pitch restrictions could be
* relaxed, but would need to store the image pitch somewhere,
* as packing details might change before image is uploaded:
*/
if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) ||
(srcRowStride & 63))
return 0;
/* Have validated that _mesa_transfer_teximage would be a straight
* memcpy at this point. NOTE: future calls to TexSubImage will
* overwrite the client data. This is explicitly mentioned in the
* extension spec.
*/
texImage->Data = (void *)pixels;
texImage->IsClientData = GL_TRUE;
texImage->RowStride = srcRowStride / texelBytes;
return 1;
}
}
static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
_mesa_store_teximage1d( ctx, target, level, internalFormat,
width, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images[0] |= (1 << level);
}
static void intelTexSubImage1D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
#if 0
struct intel_context *intel = intel_context(ctx);
struct intel_texture_object *intelObj = intel_texture_object(texObj);
return
intelObj->mt &&
intelObj->mt->region &&
intel_is_region_resident(intel, intelObj->mt->region);
#endif
return 1;
}
/* Handles 2D, CUBE, RECT:
static struct gl_texture_image *intelNewTextureImage( GLcontext *ctx )
{
(void) ctx;
return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image);
}
static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx,
GLuint name,
GLenum target )
{
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
_mesa_initialize_texture_object(&obj->base, name, target);
return &obj->base;
}
static void intelFreeTextureImageData( GLcontext *ctx,
struct gl_texture_image *texImage )
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
if (intelImage->mt) {
intel_miptree_release(intel, &intelImage->mt);
}
if (texImage->Data) {
free(texImage->Data);
texImage->Data = NULL;
}
}
#ifndef __x86_64__
static unsigned
fastrdtsc(void)
{
unsigned eax;
__asm__ volatile ("\t"
"pushl %%ebx\n\t"
"cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax)
:"0"(0)
:"ecx", "edx", "cc");
return eax;
}
#else
static unsigned
fastrdtsc(void)
{
unsigned eax;
__asm__ volatile ("\t"
"cpuid\n\t" ".byte 0x0f, 0x31\n\t" :"=a" (eax)
:"0"(0)
:"ecx", "edx", "ebx", "cc");
return eax;
}
#endif
static unsigned
time_diff(unsigned t, unsigned t2)
{
return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
}
/* The system memcpy (at least on ubuntu 5.10) has problems copying
* to agp (writecombined) memory from a source which isn't 64-byte
* aligned - there is a 4x performance falloff.
*
* The x86 __memcpy is immune to this but is slightly slower
* (10%-ish) than the system memcpy.
*
* The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
* isn't much faster than x86_memcpy for agp copies.
*
* TODO: switch dynamically.
*/
static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
static void *do_memcpy( void *dest, const void *src, size_t n )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
if ( (((unsigned)src) & 63) ||
(((unsigned)dest) & 63)) {
return __memcpy(dest, src, n);
}
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,
internalFormat,
width, height,
format, type, pixels,
packing, texObj, texImage)) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
}
else {
_mesa_store_teximage2d( ctx, target, level, internalFormat,
width, height, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images[face] |= (1 << level);
}
}
static void intelTexSubImage2D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
if (texImage->IsClientData &&
(char *)pixels == (char *)texImage->Data +
((xoffset + yoffset * texImage->RowStride) *
texImage->TexFormat->TexelBytes)) {
/* Notification only - no upload required */
}
else {
assert( t ); /* this _should_ be true */
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
t->dirty_images[face] |= (1 << level);
}
}
static void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
assert(t);
intelFlush( ctx );
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
_mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
height, border, imageSize, data, texObj, texImage);
t->dirty_images[face] |= (1 << level);
else
return memcpy(dest, src, n);
}
static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
static void *timed_memcpy( void *dest, const void *src, size_t n )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
GLuint face;
void *ret;
unsigned t1, t2;
double rate;
if ( (((unsigned)src) & 63) ||
(((unsigned)dest) & 63))
_mesa_printf("Warning - non-aligned texture copy!\n");
/* which cube face or ordinary 2D image */
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
ASSERT(face < 6);
break;
default:
face = 0;
}
t1 = fastrdtsc();
ret = do_memcpy(dest, src, n);
t2 = fastrdtsc();
assert( t ); /* this _should_ be true */
intelFlush( ctx );
driSwapOutTextureObject( t );
_mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, imageSize, data, texObj, texImage);
t->dirty_images[face] |= (1 << level);
rate = time_diff(t1, t2);
rate /= (double) n;
_mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate);
return ret;
}
static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
void intelInitTextureFuncs(struct dd_function_table * functions)
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
functions->ChooseTextureFormat = intelChooseTextureFormat;
functions->TexImage1D = intelTexImage1D;
functions->TexImage2D = intelTexImage2D;
functions->TexImage3D = intelTexImage3D;
functions->TexSubImage1D = intelTexSubImage1D;
functions->TexSubImage2D = intelTexSubImage2D;
functions->TexSubImage3D = intelTexSubImage3D;
functions->CopyTexImage1D = intelCopyTexImage1D;
functions->CopyTexImage2D = intelCopyTexImage2D;
functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
functions->NewTextureObject = intelNewTextureObject;
functions->NewTextureImage = intelNewTextureImage;
functions->DeleteTexture = _mesa_delete_texture_object;
functions->FreeTexImageData = intelFreeTextureImageData;
functions->UpdateTexturePalette = 0;
functions->IsTextureResident = intelIsTextureResident;
assert(t);
driSwapOutTextureObject( t );
texImage->IsClientData = GL_FALSE;
_mesa_store_teximage3d(ctx, target, level, internalFormat,
width, height, depth, border,
format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void
intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert( t ); /* this _should_ be true */
driSwapOutTextureObject( t );
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
{
driTextureObject * t = (driTextureObject *) tObj->DriverData;
if ( t != NULL ) {
intelFlush( ctx );
driDestroyTextureObject( t );
}
/* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, tObj);
}
static const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
intel->intelScreen->tex.size > 4*1024*1024);
switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
return &_mesa_texformat_a8;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
return &_mesa_texformat_l8;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
return &_mesa_texformat_i8;
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
case GL_COMPRESSED_RGB_FXT1_3DFX:
return &_mesa_texformat_rgb_fxt1;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
return &_mesa_texformat_rgba_fxt1;
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return &_mesa_texformat_rgb_dxt1;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return &_mesa_texformat_rgba_dxt1;
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
return &_mesa_texformat_rgba_dxt3;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return &_mesa_texformat_rgba_dxt5;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
return &_mesa_texformat_depth_component16;
default:
fprintf(stderr, "unexpected texture format %s in %s\n",
_mesa_lookup_enum_by_nr(internalFormat),
__FUNCTION__);
return NULL;
}
return NULL; /* never get here */
}
void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
{
unsigned i;
if ( intel == NULL )
return;
if ( t->age > intel->dirtyAge )
intel->dirtyAge = t->age;
for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
if ( t == intel->CurrentTexObj[ i ] )
intel->CurrentTexObj[ i ] = NULL;
}
}
/* Upload an image from mesa's internal copy. Image may be 1D, 2D or
* 3D. Cubemaps are expanded elsewhere.
*/
static void intelUploadTexImage( intelContextPtr intel,
intelTextureObjectPtr t,
const struct gl_texture_image *image,
const GLuint offset )
{
if (!image || !image->Data)
return;
if (image->Depth == 1 && image->IsClientData) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "Blit uploading\n");
/* Do it with a blit.
*/
intelEmitCopyBlitLocked( intel,
image->TexFormat->TexelBytes,
image->RowStride, /* ? */
intelGetMemoryOffsetMESA( NULL, 0, image->Data ),
t->Pitch / image->TexFormat->TexelBytes,
intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ),
0, 0,
0, 0,
image->Width,
image->Height);
}
else if (image->IsCompressed) {
GLuint row_len = image->Width * 2;
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
GLubyte *src = (GLubyte *)image->Data;
GLuint j;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr,
"Upload image %dx%dx%d offset %xm row_len %x "
"pitch %x depth_pitch %x\n",
image->Width, image->Height, image->Depth, offset,
row_len, t->Pitch, t->depth_pitch);
switch (image->InternalFormat) {
case GL_COMPRESSED_RGB_FXT1_3DFX:
case GL_COMPRESSED_RGBA_FXT1_3DFX:
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
__memcpy(dst, src, row_len );
src += row_len;
}
break;
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
__memcpy(dst, src, (image->Width*4) );
src += image->Width*4;
}
break;
default:
fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat);
break;
}
}
else {
GLuint row_len = image->Width * image->TexFormat->TexelBytes;
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
GLubyte *src = (GLubyte *)image->Data;
GLuint d, j;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr,
"Upload image %dx%dx%d offset %xm row_len %x "
"pitch %x depth_pitch %x\n",
image->Width, image->Height, image->Depth, offset,
row_len, t->Pitch, t->depth_pitch);
if (row_len == t->Pitch) {
for (d = 0; d < image->Depth; d++) {
memcpy( dst, src, t->Pitch * image->Height );
dst += t->depth_pitch;
src += row_len * image->Height;
}
}
else {
for (d = 0 ; d < image->Depth ; d++) {
for (j = 0 ; j < image->Height ; j++) {
__memcpy(dst, src, row_len );
src += row_len;
dst += t->Pitch;
}
dst += t->depth_pitch - (t->Pitch * image->Height);
}
}
}
}
int intelUploadTexImages( intelContextPtr intel,
intelTextureObjectPtr t,
GLuint face)
{
const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image;
int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes;
/* Can we texture out of the existing client data? */
if ( numLevels == 1 &&
firstImage->IsClientData &&
(pitch & 3) == 0) {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "AGP texturing from client memory\n");
t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data );
t->BufAddr = 0;
t->dirty = ~0;
return GL_TRUE;
}
else {
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "Uploading client data to agp\n");
INTEL_FIREVERTICES( intel );
LOCK_HARDWARE( intel );
if ( t->base.memBlock == NULL ) {
int heap;
heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps,
(driTextureObject *) t );
if ( heap == -1 ) {
UNLOCK_HARDWARE( intel );
return GL_FALSE;
}
/* Set the base offset of the texture image */
t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs;
t->dirty = ~0;
}
/* Let the world know we've used this memory recently.
*/
driUpdateTextureLRU( (driTextureObject *) t );
/* Upload any images that are new */
if (t->base.dirty_images[face]) {
int i;
intelWaitForIdle( intel );
for (i = 0 ; i < numLevels ; i++) {
int level = i + t->base.firstLevel;
if (t->base.dirty_images[face] & (1<<level)) {
const struct gl_texture_image *image = t->image[face][i].image;
GLuint offset = t->image[face][i].offset;
if (INTEL_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, "upload level %d, offset %x\n",
level, offset);
intelUploadTexImage( intel, t, image, offset );
}
}
t->base.dirty_images[face] = 0;
intel->perf_boxes |= I830_BOX_TEXTURE_LOAD;
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
}
/**
* Allocate a new texture object.
* Called via ctx->Driver.NewTextureObject.
* Note: this function will be called during context creation to
* allocate the default texture objects.
* Note: we could use containment here to 'derive' the driver-specific
* texture object from the core mesa gl_texture_object. Not done at this time.
*/
static struct gl_texture_object *
intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
{
struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target);
INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj );
return obj;
}
void intelInitTextureFuncs( struct dd_function_table *functions )
{
functions->NewTextureObject = intelNewTextureObject;
functions->ChooseTextureFormat = intelChooseTextureFormat;
functions->TexImage1D = intelTexImage1D;
functions->TexImage2D = intelTexImage2D;
functions->TexImage3D = intelTexImage3D;
functions->TexSubImage1D = intelTexSubImage1D;
functions->TexSubImage2D = intelTexSubImage2D;
functions->TexSubImage3D = intelTexSubImage3D;
functions->CopyTexImage1D = _swrast_copy_teximage1d;
functions->CopyTexImage2D = _swrast_copy_teximage2d;
functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
functions->DeleteTexture = intelDeleteTexture;
functions->UpdateTexturePalette = NULL;
functions->IsTextureResident = driIsTextureResident;
functions->TestProxyTexImage = _mesa_test_proxy_teximage;
functions->DeleteTexture = intelDeleteTexture;
functions->CompressedTexImage2D = intelCompressedTexImage2D;
functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
if (INTEL_DEBUG & DEBUG_BUFMGR)
functions->TextureMemCpy = timed_memcpy;
else
functions->TextureMemCpy = do_memcpy;
}

View File

@@ -35,8 +35,97 @@
void intelInitTextureFuncs( struct dd_function_table *functions );
void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t );
int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t,
GLuint face );
const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type );
void intelTexImage3D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexSubImage3D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexImage2D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexSubImage2D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexImage1D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelTexSubImage1D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage);
void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width,
GLint border );
void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border );
void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset,
GLint x, GLint y, GLsizei width );
void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height );
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit );
void intel_tex_map_images( struct intel_context *intel,
struct intel_texture_object *intelObj );
void intel_tex_unmap_images( struct intel_context *intel,
struct intel_texture_object *intelObj );
#endif

View File

@@ -0,0 +1,303 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "mtypes.h"
#include "enums.h"
#include "teximage.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_tex.h"
#include "intel_blit.h"
#include "intel_pixel.h"
#include "bufmgr.h"
/* Do the best we can using the blitter. A future project is to use
* the texture engine and fragment programs for these copies.
*/
static struct intel_region *get_teximage_source( struct intel_context *intel,
GLenum internalFormat )
{
if (0)
_mesa_printf("%s %s\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(internalFormat));
switch (internalFormat) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_ARB:
if (intel->intelScreen->cpp == 2)
return intel->depth_region;
return NULL;
case GL_DEPTH24_STENCIL8_EXT:
case GL_DEPTH_STENCIL_EXT:
if (intel->intelScreen->cpp == 4)
return intel->depth_region;
return NULL;
case GL_RGBA:
return intel_readbuf_region( intel );
case GL_RGB:
if (intel->intelScreen->cpp == 2)
return intel_readbuf_region( intel );
return NULL;
default:
return NULL;
}
}
static GLboolean check_copytex_fragment_ops( const GLcontext *ctx )
{
return GL_TRUE;
return !(ctx->Color.AlphaEnabled ||
/* ctx->Depth.Test || */
ctx->Fog.Enabled ||
/* ctx->Scissor.Enabled || */
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits);
}
static GLboolean do_copy_texsubimage( struct intel_context *intel,
struct intel_texture_image *intelImage,
GLenum internalFormat,
GLint dstx, GLint dsty,
GLint x, GLint y,
GLsizei width, GLsizei height )
{
GLcontext *ctx = &intel->ctx;
struct intel_region *src = get_teximage_source(intel, internalFormat);
GLuint ret = GL_TRUE;
if (!intelImage->mt || !src)
return GL_FALSE;
if (!check_copytex_fragment_ops( ctx ))
return GL_FALSE;
intelFlush(ctx);
LOCK_HARDWARE(intel);
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
GLuint image_offset = intel_miptree_image_offset(intelImage->mt,
intelImage->face,
intelImage->level);
GLint orig_x = x;
GLint orig_y = y;
GLuint window_y;
if (!intel_clip_to_framebuffer(ctx, ctx->DrawBuffer, &x, &y, &width, &height)) {
ret = GL_TRUE;
goto out;
}
/* Update dst for clipped src. Need to also clip the source rect.
*/
dstx += x - orig_x;
dsty += y - orig_y;
x += dPriv->x;
window_y = intel->intelScreen->height - (dPriv->y + dPriv->h);
y = window_y + y;
/* A bit of fiddling to get the blitter to work with -ve
* pitches. But we get a nice inverted blit this way, so it's
* worth it:
*/
intelEmitCopyBlit( intel,
intelImage->mt->cpp,
-src->pitch,
src->buffer,
src->height * src->pitch * src->cpp,
intelImage->mt->pitch,
intelImage->mt->region->buffer,
image_offset,
x, y + height,
dstx, dsty,
width, height );
out:
intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE(intel);
if (!ret)
return GL_FALSE;
#if 0
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
*/
if (level == texObj->BaseLevel &&
texObj->GenerateMipmap) {
intel_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
return GL_TRUE;
}
void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width,
GLint border )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (border)
goto fail;
/* Setup or redefine the texture object, mipmap tree and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
width, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
0, 0,
x, y,
width, 1))
goto fail;
return;
fail:
_swrast_copy_teximage1d( ctx, target, level, internalFormat, x, y,
width, border );
}
void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (border)
goto fail;
/* Setup or redefine the texture object, mipmap tree and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
width, height, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
0, 0,
x, y,
width, height))
goto fail;
return;
fail:
_swrast_copy_teximage2d( ctx, target, level, internalFormat, x, y,
width, height, border );
}
void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset,
GLint x, GLint y, GLsizei width )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
GLenum internalFormat = texImage->InternalFormat;
/* Need to check texture is compatible with source format.
*/
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
xoffset, 0,
x, y, width, 1)) {
_swrast_copy_texsubimage1d( ctx, target, level,
xoffset, x, y, width );
}
}
void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
GLenum internalFormat = texImage->InternalFormat;
/* Need to check texture is compatible with source format.
*/
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
xoffset, yoffset,
x, y, width, height)) {
_swrast_copy_texsubimage2d( ctx, target, level,
xoffset, yoffset,
x, y, width, height );
}
}

View File

@@ -0,0 +1,148 @@
#include "intel_context.h"
#include "intel_tex.h"
#include "texformat.h"
#include "enums.h"
/* It works out that this function is fine for all the supported
* hardware. However, there is still a need to map the formats onto
* hardware descriptors.
*/
/* Note that the i915 can actually support many more formats than
* these if we take the step of simply swizzling the colors
* immediately after sampling...
*/
const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
struct intel_context *intel = intel_context( ctx );
const GLboolean do32bpt = (intel->intelScreen->cpp == 4);
switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return &_mesa_texformat_argb8888;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
return &_mesa_texformat_a8;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
return &_mesa_texformat_l8;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
return &_mesa_texformat_i8;
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
case GL_COMPRESSED_RGB_FXT1_3DFX:
return &_mesa_texformat_rgb_fxt1;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
return &_mesa_texformat_rgba_fxt1;
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return &_mesa_texformat_rgb_dxt1;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return &_mesa_texformat_rgba_dxt1;
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
return &_mesa_texformat_rgba_dxt3;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return &_mesa_texformat_rgba_dxt5;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
return &_mesa_texformat_depth_component16;
default:
fprintf(stderr, "unexpected texture format %s in %s\n",
_mesa_lookup_enum_by_nr(internalFormat),
__FUNCTION__);
return NULL;
}
return NULL; /* never get here */
}

View File

@@ -0,0 +1,400 @@
#include <stdlib.h>
#include <stdio.h>
#include "glheader.h"
#include "macros.h"
#include "mtypes.h"
#include "enums.h"
#include "colortab.h"
#include "convolve.h"
#include "context.h"
#include "simple_list.h"
#include "texcompress.h"
#include "texformat.h"
#include "texobj.h"
#include "texstore.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_ioctl.h"
/* Functions to store texture images. Where possible, mipmap_tree's
* will be created or further instantiated with image data, otherwise
* images will be stored in malloc'd memory. A validation step is
* required to pull those images into a mipmap tree, or otherwise
* decide a fallback is required.
*/
static int logbase2(int n)
{
GLint i = 1;
GLint log2 = 0;
while (n > i) {
i *= 2;
log2++;
}
return log2;
}
/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
* 1).
*
* Otherwise, if max_level >= level >= min_level, create tree with
* space for textures from min_level down to max_level.
*
* Otherwise, create tree with space for textures from (level
* 0)..(1x1). Consider pruning this tree at a validation if the
* saving is worth it.
*/
static void guess_and_alloc_mipmap_tree( struct intel_context *intel,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage )
{
GLuint firstLevel;
GLuint lastLevel;
GLuint width = intelImage->base.Width;
GLuint height = intelImage->base.Height;
GLuint depth = intelImage->base.Depth;
GLuint l2width, l2height, l2depth;
GLuint i;
DBG("%s\n", __FUNCTION__);
if (intelImage->base.Border)
return;
if (intelImage->level > intelObj->base.BaseLevel &&
(intelImage->base.Width == 1 ||
(intelObj->base.Target != GL_TEXTURE_1D &&
intelImage->base.Height == 1) ||
(intelObj->base.Target == GL_TEXTURE_3D &&
intelImage->base.Depth == 1)))
return;
/* If this image disrespects BaseLevel, allocate from level zero.
* Usually BaseLevel == 0, so it's unlikely to happen.
*/
if (intelImage->level < intelObj->base.BaseLevel)
firstLevel = 0;
else
firstLevel = intelObj->base.BaseLevel;
/* Figure out image dimensions at start level.
*/
for (i = intelImage->level; i > firstLevel; i--) {
width <<= 1;
if (height != 1) height <<= 1;
if (depth != 1) depth <<= 1;
}
/* Guess a reasonable value for lastLevel. This is probably going
* to be wrong fairly often and might mean that we have to look at
* resizable buffers, or require that buffers implement lazy
* pagetable arrangements.
*/
if ((intelObj->base.MinFilter == GL_NEAREST ||
intelObj->base.MinFilter == GL_LINEAR) &&
intelImage->level == firstLevel) {
lastLevel = firstLevel;
}
else {
l2width = logbase2(width);
l2height = logbase2(height);
l2depth = logbase2(depth);
lastLevel = firstLevel + MAX2(MAX2(l2width,l2height),l2depth);
}
assert(!intelObj->mt);
intelObj->mt = intel_miptree_create( intel,
intelObj->base.Target,
intelImage->base.InternalFormat,
firstLevel,
lastLevel,
width,
height,
depth,
intelImage->base.TexFormat->TexelBytes,
intelImage->base.IsCompressed );
DBG("%s - success\n", __FUNCTION__);
}
static GLuint target_to_face( GLenum target )
{
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
return ((GLuint) target -
(GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
default:
return 0;
}
}
static void intelTexImage(GLcontext *ctx,
GLint dims,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_object *intelObj = intel_texture_object(texObj);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
GLint postConvWidth = width;
GLint postConvHeight = height;
GLint texelBytes, sizeInBytes;
GLuint dstRowStride;
GLuint dstImageStride;
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level,
width, height, depth, border);
intelFlush(ctx);
intelImage->face = target_to_face( target );
intelImage->level = level;
if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
_mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
&postConvHeight);
}
/* choose the texture format */
texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat,
format, type);
assert(texImage->TexFormat);
switch (dims) {
case 1:
texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
break;
case 2:
texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
break;
case 3:
texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
break;
default:
assert(0);
break;
}
texelBytes = texImage->TexFormat->TexelBytes;
/* Minimum pitch of 32 bytes */
if (postConvWidth * texelBytes < 32) {
postConvWidth = 32 / texelBytes;
texImage->RowStride = postConvWidth;
}
assert(texImage->RowStride == postConvWidth);
/* Release the reference to a potentially orphaned buffer.
* Release any old malloced memory.
*/
if (intelImage->mt) {
intel_miptree_release(intel, &intelImage->mt);
assert(!texImage->Data);
}
else if (texImage->Data) {
free(texImage->Data);
}
/* If this is the only texture image in the tree, could call
* bmBufferData with NULL data to free the old block and avoid
* waiting on any outstanding fences.
*/
if (intelObj->mt &&
intelObj->mt->first_level == level &&
intelObj->mt->last_level == level &&
intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
!intel_miptree_match_image(intelObj->mt, &intelImage->base,
intelImage->face, intelImage->level)) {
DBG("release it\n");
intel_miptree_release(intel, &intelObj->mt);
assert(!intelObj->mt);
}
if (!intelObj->mt) {
guess_and_alloc_mipmap_tree(intel, intelObj, intelImage);
if (!intelObj->mt)
_mesa_printf("guess_and_alloc_mipmap_tree: failed\n");
}
if (intelObj->mt &&
intelObj->mt != intelImage->mt &&
intel_miptree_match_image(intelObj->mt, &intelImage->base,
intelImage->face, intelImage->level)) {
if (intelImage->mt) {
intel_miptree_release(intel, &intelImage->mt);
}
intel_miptree_reference(&intelImage->mt, intelObj->mt);
assert(intelImage->mt);
}
if (!intelImage->mt)
_mesa_printf("XXX: Image did not fit into tree - storing in local memory!\n");
/* intelCopyTexImage calls this function with pixels == NULL, with
* the expectation that the mipmap tree will be set up but nothing
* more will be done. This is where those calls return:
*/
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
format, type,
pixels, unpack, "glTexImage");
if (!pixels)
return;
LOCK_HARDWARE(intel);
if (intelImage->mt) {
texImage->Data = intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&dstRowStride,
&dstImageStride);
}
else {
/* Allocate regular memory and store the image there temporarily. */
if (texImage->IsCompressed) {
sizeInBytes = texImage->CompressedSize;
dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width);
dstImageStride = 0; /* ? */
assert(dims != 3);
}
else {
dstRowStride = postConvWidth * texelBytes;
dstImageStride = dstRowStride * postConvHeight;
sizeInBytes = depth * dstImageStride;
}
texImage->Data = malloc(sizeInBytes);
}
fprintf(stderr,
"Upload image %dx%dx%d row_len %x "
"pitch %x depth_pitch %x\n",
width, height, depth,
width * texelBytes, dstRowStride, dstImageStride);
/* Copy data. Would like to know when it's ok for us to eg. use
* the blitter to copy. Or, use the hardware to do the format
* conversion and copy:
*/
if (!texImage->TexFormat->StoreImage(ctx, dims,
texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
0, 0, 0, /* dstX/Y/Zoffset */
dstRowStride, dstImageStride,
width, height, depth,
format, type, pixels, unpack)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
}
_mesa_unmap_teximage_pbo(ctx, unpack);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
texImage->Data = NULL;
}
UNLOCK_HARDWARE(intel);
#if 0
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
*/
if (level == texObj->BaseLevel &&
texObj->GenerateMipmap) {
intel_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
}
void intelTexImage3D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexImage( ctx, 3, target, level,
internalFormat, width, height, depth, border,
format, type, pixels,
unpack, texObj, texImage );
}
void intelTexImage2D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexImage( ctx, 2, target, level,
internalFormat, width, height, 1, border,
format, type, pixels,
unpack, texObj, texImage );
}
void intelTexImage1D(GLcontext *ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexImage( ctx, 1, target, level,
internalFormat, width, 1, 1, border,
format, type, pixels,
unpack, texObj, texImage );
}

View File

@@ -0,0 +1,178 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
*
**************************************************************************/
#include "mtypes.h"
#include "texobj.h"
#include "texstore.h"
#include "enums.h"
#include "intel_context.h"
#include "intel_tex.h"
#include "intel_mipmap_tree.h"
static void intelTexSubimage (GLcontext *ctx,
GLint dims,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
GLuint dstImageStride;
GLuint dstRowStride;
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level,
xoffset, yoffset,
width, height);
intelFlush(ctx);
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type,
pixels, packing, "glTexSubImage2D");
if (!pixels)
return;
LOCK_HARDWARE(intel);
/* Map buffer if necessary. Need to lock to prevent other contexts
* from uploading the buffer under us.
*/
if (intelImage->mt)
texImage->Data = intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&dstRowStride,
&dstImageStride );
assert(dstRowStride);
if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
xoffset, yoffset, zoffset,
dstRowStride, dstImageStride,
width, height, depth,
format, type, pixels, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
}
#if 0
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
_mesa_unmap_teximage_pbo(ctx, packing);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
texImage->Data = NULL;
}
UNLOCK_HARDWARE(intel);
}
void intelTexSubImage3D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 3,
target, level,
xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj,
texImage);
}
void intelTexSubImage2D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 2,
target, level,
xoffset, yoffset, 0,
width, height, 1,
format, type, pixels, packing, texObj,
texImage);
}
void intelTexSubImage1D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 1,
target, level,
xoffset, 0, 0,
width, 1, 1,
format, type, pixels, packing, texObj,
texImage);
}

View File

@@ -0,0 +1,249 @@
#include "mtypes.h"
#include "macros.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "bufmgr.h"
/**
* Compute which mipmap levels that really need to be sent to the hardware.
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
*/
static void intel_calculate_first_last_level( struct intel_texture_object *intelObj )
{
struct gl_texture_object *tObj = &intelObj->base;
const struct gl_texture_image * const baseImage =
tObj->Image[0][tObj->BaseLevel];
/* These must be signed values. MinLod and MaxLod can be negative numbers,
* and having firstLevel and lastLevel as signed prevents the need for
* extra sign checks.
*/
int firstLevel;
int lastLevel;
/* Yes, this looks overly complicated, but it's all needed.
*/
switch (tObj->Target) {
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP:
if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
*/
firstLevel = lastLevel = tObj->BaseLevel;
}
else {
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
}
break;
case GL_TEXTURE_RECTANGLE_NV:
case GL_TEXTURE_4D_SGIS:
firstLevel = lastLevel = 0;
break;
default:
return;
}
/* save these values */
intelObj->firstLevel = firstLevel;
intelObj->lastLevel = lastLevel;
}
static void copy_image_data_to_tree( struct intel_context *intel,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage )
{
if (intelImage->mt) {
/* Copy potentially with the blitter:
*/
intel_miptree_image_copy(intel,
intelObj->mt,
intelImage->face,
intelImage->level,
intelImage->mt);
intel_miptree_release(intel, &intelImage->mt);
}
else {
assert(intelImage->base.Data != NULL);
/* More straightforward upload.
*/
intel_miptree_image_data(intel,
intelObj->mt,
intelImage->face,
intelImage->level,
intelImage->base.Data,
intelImage->base.RowStride,
intelImage->base.RowStride * intelImage->base.Height);
free(intelImage->base.Data);
intelImage->base.Data = NULL;
}
intel_miptree_reference(&intelImage->mt, intelObj->mt);
}
/*
*/
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit )
{
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
GLuint face, i;
GLuint nr_faces = 0;
struct intel_texture_image *firstImage;
/* We know/require this is true by now:
*/
assert(intelObj->base.Complete);
/* What levels must the tree include at a minimum?
*/
intel_calculate_first_last_level( intelObj );
firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);
/* Fallback case:
*/
if (firstImage->base.Border) {
if (intelObj->mt) {
intel_miptree_release(intel, &intelObj->mt);
}
return GL_FALSE;
}
/* If both firstImage and intelObj have a tree which can contain
* all active images, favour firstImage. Note that because of the
* completeness requirement, we know that the image dimensions
* will match.
*/
if (firstImage->mt &&
firstImage->mt != intelObj->mt &&
firstImage->mt->first_level <= intelObj->firstLevel &&
firstImage->mt->last_level >= intelObj->lastLevel) {
if (intelObj->mt)
intel_miptree_release(intel, &intelObj->mt);
intel_miptree_reference(&intelObj->mt, firstImage->mt);
}
/* Check tree can hold all active levels. Check tree matches
* target, imageFormat, etc.
*
* XXX: For some layouts (eg i945?), the test might have to be
* first_level == firstLevel, as the tree isn't valid except at the
* original start level. Hope to get around this by
* programming minLod, maxLod, baseLevel into the hardware and
* leaving the tree alone.
*/
if (intelObj->mt &&
((intelObj->mt->first_level > intelObj->firstLevel) ||
(intelObj->mt->last_level < intelObj->lastLevel) ||
(intelObj->mt->internal_format != firstImage->base.InternalFormat))) {
intel_miptree_release(intel, &intelObj->mt);
}
/* May need to create a new tree:
*/
if (!intelObj->mt) {
intelObj->mt = intel_miptree_create(intel,
intelObj->base.Target,
firstImage->base.InternalFormat,
intelObj->firstLevel,
intelObj->lastLevel,
firstImage->base.Width,
firstImage->base.Height,
firstImage->base.Depth,
firstImage->base.TexFormat->TexelBytes,
firstImage->base.IsCompressed);
}
/* Pull in any images not in the object's tree:
*/
nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
/* Need to import images in main memory or held in other trees.
*/
if (intelObj->mt != intelImage->mt) {
copy_image_data_to_tree(intel,
intelObj,
intelImage);
}
}
}
return GL_TRUE;
}
void intel_tex_map_images( struct intel_context *intel,
struct intel_texture_object *intelObj )
{
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face, i;
DBG("%s\n", __FUNCTION__);
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
/* XXX: Fallbacks will fail for 3d textures because core mesa
* doesn't have a place to put ImageStride -- assumes each
* teximage's depth slices are packed contiguously. This
* isn't true for i915.
*/
if (intelImage->mt) {
intelImage->base.Data =
intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&intelImage->base.RowStride,
NULL);
}
}
}
}
void intel_tex_unmap_images( struct intel_context *intel,
struct intel_texture_object *intelObj )
{
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face, i;
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
intelImage->base.Data = NULL;
}
}
}
}

View File

@@ -38,14 +38,108 @@
#include "tnl/t_vertex.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_tris.h"
#include "intel_batchbuffer.h"
#include "intel_reg.h"
#include "intel_span.h"
#include "intel_tex.h"
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
/* The simplest but least-good technique for integrating new buffer
* management:
*
* LOCK_HARDWARE
* validate_buffers
* emit_state to batch
* emit_vertices to batch
* flush batch
* fence_buffers
* UNLOCK_HARDWARE
*
* Will look later at ways to get the emit_state and emit_vertices out
* of the locked region - vertex buffers, second batch buffer for
* primitives, relocation fixups for texture addresses.
*/
static void intel_flush_inline_primitive( struct intel_context *intel )
{
GLuint used = intel->batch->ptr - intel->prim.start_ptr;
assert(intel->prim.primitive != ~0);
if (used < 8)
goto do_discard;
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
intel->prim.primitive |
(used/4-2));
goto finished;
do_discard:
intel->batch->ptr -= used;
finished:
intel->prim.primitive = ~0;
intel->prim.start_ptr = 0;
intel->prim.flush = 0;
}
/* Emit a primitive referencing vertices in a vertex buffer.
*/
void intelStartInlinePrimitive( struct intel_context *intel,
GLuint prim,
GLuint batch_flags )
{
BATCH_LOCALS;
/* Emit a slot which will be filled with the inline primitive
* command later.
*/
BEGIN_BATCH(2, batch_flags);
OUT_BATCH( 0 );
intel->prim.start_ptr = intel->batch->ptr;
intel->prim.primitive = prim;
intel->prim.flush = intel_flush_inline_primitive;
OUT_BATCH( 0 );
ADVANCE_BATCH();
}
void intelWrapInlinePrimitive( struct intel_context *intel )
{
GLuint prim = intel->prim.primitive;
GLuint batchflags = intel->batch->flags;
intel_flush_inline_primitive(intel);
intel_batchbuffer_flush(intel->batch);
intel->vtbl.emit_state( intel );
intelStartInlinePrimitive( intel, prim, batchflags ); /* ??? */
}
GLuint *intelExtendInlinePrimitive( struct intel_context *intel,
GLuint dwords )
{
GLuint sz = dwords * sizeof(GLuint);
GLuint *ptr;
if (intel_batchbuffer_space(intel->batch) < sz)
intelWrapInlinePrimitive( intel );
ptr = (GLuint *)intel->batch->ptr;
intel->batch->ptr += sz;
return ptr;
}
/***********************************************************************
* Emit primitives as inline vertices *
***********************************************************************/
@@ -63,22 +157,18 @@ do { \
#else
#define COPY_DWORDS( j, vb, vertsize, v ) \
do { \
if (0) fprintf(stderr, "\n"); \
for ( j = 0 ; j < vertsize ; j++ ) { \
if (0) fprintf(stderr, " -- v(%d): %x/%f\n",j, \
((GLuint *)v)[j], \
((GLfloat *)v)[j]); \
vb[j] = ((GLuint *)v)[j]; \
} \
vb += vertsize; \
} while (0)
#endif
static void __inline__ intel_draw_quad( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2,
intelVertexPtr v3 )
static void intel_draw_quad( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2,
intelVertexPtr v3 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize );
@@ -92,10 +182,10 @@ static void __inline__ intel_draw_quad( intelContextPtr intel,
COPY_DWORDS( j, vb, vertsize, v3 );
}
static void __inline__ intel_draw_triangle( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
static void intel_draw_triangle( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 3 * vertsize );
@@ -107,9 +197,9 @@ static void __inline__ intel_draw_triangle( intelContextPtr intel,
}
static __inline__ void intel_draw_line( intelContextPtr intel,
intelVertexPtr v0,
intelVertexPtr v1 )
static void intel_draw_line( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, 2 * vertsize );
@@ -120,8 +210,8 @@ static __inline__ void intel_draw_line( intelContextPtr intel,
}
static __inline__ void intel_draw_point( intelContextPtr intel,
intelVertexPtr v0 )
static void intel_draw_point( struct intel_context *intel,
intelVertexPtr v0 )
{
GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, vertsize );
@@ -140,7 +230,7 @@ static __inline__ void intel_draw_point( intelContextPtr intel,
* Fixup for ARB_point_parameters *
***********************************************************************/
static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
static void intel_atten_point( struct intel_context *intel, intelVertexPtr v0 )
{
GLcontext *ctx = &intel->ctx;
GLfloat psz[4], col[4], restore_psz, restore_alpha;
@@ -189,7 +279,7 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
static void intel_wpos_triangle( intelContextPtr intel,
static void intel_wpos_triangle( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1,
intelVertexPtr v2 )
@@ -205,7 +295,7 @@ static void intel_wpos_triangle( intelContextPtr intel,
}
static void intel_wpos_line( intelContextPtr intel,
static void intel_wpos_line( struct intel_context *intel,
intelVertexPtr v0,
intelVertexPtr v1 )
{
@@ -219,7 +309,7 @@ static void intel_wpos_line( intelContextPtr intel,
}
static void intel_wpos_point( intelContextPtr intel,
static void intel_wpos_point( struct intel_context *intel,
intelVertexPtr v0 )
{
GLuint offset = intel->wpos_offset;
@@ -349,7 +439,7 @@ do { \
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
#define LOCAL_VARS(n) \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
struct intel_context *intel = intel_context(ctx); \
GLuint color[n], spec[n]; \
GLuint coloroffset = intel->coloroffset; \
GLboolean specoffset = intel->specoffset; \
@@ -481,7 +571,7 @@ static void init_rast_tab( void )
* primitives.
*/
static void
intel_fallback_tri( intelContextPtr intel,
intel_fallback_tri( struct intel_context *intel,
intelVertex *v0,
intelVertex *v1,
intelVertex *v2 )
@@ -502,7 +592,7 @@ intel_fallback_tri( intelContextPtr intel,
static void
intel_fallback_line( intelContextPtr intel,
intel_fallback_line( struct intel_context *intel,
intelVertex *v0,
intelVertex *v1 )
{
@@ -520,22 +610,6 @@ intel_fallback_line( intelContextPtr intel,
}
static void
intel_fallback_point( intelContextPtr intel,
intelVertex *v0 )
{
GLcontext *ctx = &intel->ctx;
SWvertex v[1];
if (0)
fprintf(stderr, "\n%s\n", __FUNCTION__);
_swsetup_Translate( ctx, v0, &v[0] );
intelSpanRenderStart( ctx );
_swrast_Point( ctx, &v[0] );
intelSpanRenderFinish( ctx );
}
/**********************************************************************/
@@ -552,7 +626,7 @@ intel_fallback_point( intelContextPtr intel,
#define INIT(x) intelRenderPrimitive( ctx, x )
#undef LOCAL_VARS
#define LOCAL_VARS \
intelContextPtr intel = INTEL_CONTEXT(ctx); \
struct intel_context *intel = intel_context(ctx); \
GLubyte *vertptr = (GLubyte *)intel->verts; \
const GLuint vertsize = intel->vertex_size; \
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
@@ -578,7 +652,7 @@ intel_fallback_point( intelContextPtr intel,
static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint prim = intel->render_primitive;
@@ -609,7 +683,7 @@ static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
intelContextPtr intel = INTEL_CONTEXT( ctx );
struct intel_context *intel = intel_context( ctx );
const GLuint vertsize = intel->vertex_size;
GLuint *vb = intelExtendInlinePrimitive( intel, (n-2) * 3 * vertsize );
GLubyte *vertptr = (GLubyte *)intel->verts;
@@ -630,17 +704,13 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
#define POINT_FALLBACK (0)
#define LINE_FALLBACK (DD_LINE_STIPPLE)
#define TRI_FALLBACK (0)
#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
DD_TRI_STIPPLE|DD_POINT_ATTEN)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
void intelChooseRenderState(GLcontext *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
GLuint flags = ctx->_TriangleCaps;
struct fragment_program *fprog = ctx->FragmentProgram._Current;
GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
@@ -672,19 +742,14 @@ void intelChooseRenderState(GLcontext *ctx)
intel->draw_tri = intel_draw_triangle;
}
#if 0
/* Hook in fallbacks for specific primitives.
*/
if (flags & ANY_FALLBACK_FLAGS)
{
if (flags & POINT_FALLBACK)
intel->draw_point = intel_fallback_point;
if (flags & LINE_FALLBACK)
if (flags & DD_LINE_STIPPLE)
intel->draw_line = intel_fallback_line;
if (flags & TRI_FALLBACK)
intel->draw_tri = intel_fallback_tri;
if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
intel->draw_tri = intel_fallback_tri;
@@ -693,6 +758,8 @@ void intelChooseRenderState(GLcontext *ctx)
index |= INTEL_FALLBACK_BIT;
}
#endif
}
if (intel->RenderIndex != index) {
@@ -740,7 +807,7 @@ static const GLenum reduced_prim[GL_POLYGON+1] = {
static void intelRunPipeline( GLcontext *ctx )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
if (intel->NewGLState) {
if (intel->NewGLState & _NEW_TEXTURE) {
@@ -760,13 +827,21 @@ static void intelRunPipeline( GLcontext *ctx )
static void intelRenderStart( GLcontext *ctx )
{
INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) );
struct intel_context *intel = intel_context(ctx);
intel->vtbl.render_start( intel_context(ctx) );
intel->vtbl.emit_state( intel );
}
static void intelRenderFinish( GLcontext *ctx )
{
if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
struct intel_context *intel = intel_context(ctx);
if (intel->RenderIndex & INTEL_FALLBACK_BIT)
_swrast_flush( ctx );
if (intel->prim.flush)
intel->prim.flush(intel);
}
@@ -777,7 +852,7 @@ static void intelRenderFinish( GLcontext *ctx )
*/
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
if (0)
fprintf(stderr, "%s %s %x\n", __FUNCTION__,
@@ -788,111 +863,175 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
/* Start a new primitive. Arrange to have it flushed later on.
*/
if (hwprim != intel->prim.primitive)
intelStartInlinePrimitive( intel, hwprim );
intelStartInlinePrimitive( intel, hwprim, INTEL_BATCH_CLIPRECTS );
}
/*
*/
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
{
intelContextPtr intel = INTEL_CONTEXT(ctx);
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
{
struct intel_context *intel = intel_context(ctx);
if (0)
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
if (0)
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
/* Let some clipping routines know which primitive they're dealing
* with.
*/
intel->render_primitive = prim;
/* Let some clipping routines know which primitive they're dealing
* with.
*/
intel->render_primitive = prim;
/* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
* triangles. The rasterized primitive will always be reset by
* lower level functions in that case, potentially pingponging the
* state:
*/
if (reduced_prim[prim] == GL_TRIANGLES &&
(ctx->_TriangleCaps & DD_TRI_UNFILLED))
return;
/* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
* triangles. The rasterized primitive will always be reset by
* lower level functions in that case, potentially pingponging the
* state:
*/
if (reduced_prim[prim] == GL_TRIANGLES &&
(ctx->_TriangleCaps & DD_TRI_UNFILLED))
return;
/* Set some primitive-dependent state and Start? a new primitive.
*/
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
}
/* Set some primitive-dependent state and Start? a new primitive.
*/
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
}
/**********************************************************************/
/* Transition to/from hardware rasterization. */
/**********************************************************************/
static char *fallbackStrings[] = {
"Texture",
"Draw buffer",
"Read buffer",
"Color mask",
"Render mode",
"Stencil",
"Stipple",
"User disable"
};
static char *fallbackStrings[] = {
"Texture",
"Draw buffer",
"Read buffer",
"Color mask",
"Render mode",
"Stencil",
"Stipple",
"User disable"
};
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
static char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode )
{
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint oldfallback = intel->Fallback;
void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode )
{
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint oldfallback = intel->Fallback;
if (mode) {
intel->Fallback |= bit;
if (oldfallback == 0) {
intelFlush(ctx);
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
bit, getFallbackString( bit ));
_swsetup_Wakeup( ctx );
intel->RenderIndex = ~0;
}
}
else {
intel->Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
tnl->Driver.Render.Start = intelRenderStart;
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
tnl->Driver.Render.Finish = intelRenderFinish;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
if (mode) {
intel->Fallback |= bit;
if (oldfallback == 0) {
intelFlush(ctx);
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
bit, getFallbackString( bit ));
_swsetup_Wakeup( ctx );
intel->RenderIndex = ~0;
}
}
else {
intel->Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
if (INTEL_DEBUG & DEBUG_FALLBACKS)
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
tnl->Driver.Render.Start = intelRenderStart;
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
tnl->Driver.Render.Finish = intelRenderFinish;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.Interp = _tnl_interp;
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
_tnl_install_attrs( ctx,
intel->vertex_attrs,
intel->vertex_attr_count,
intel->ViewportMatrix.m, 0 );
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
_tnl_install_attrs( ctx,
intel->vertex_attrs,
intel->vertex_attr_count,
intel->ViewportMatrix.m, 0 );
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
}
}
}
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
}
}
}
/**********************************************************************/
/* Used only with the metaops callbacks. */
/**********************************************************************/
void intel_meta_draw_quad(struct intel_context *intel,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLfloat z,
GLuint color,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1,
GLuint flags)
{
union fi *vb;
if (0)
fprintf(stderr, "%s: %f,%f-%f,%f 0x%x %f,%f-%f,%f\n",
__FUNCTION__,
x0,y0,x1,y1,color,s0,t0,s1,t1);
intel->vtbl.emit_state( intel );
intelStartInlinePrimitive( intel, PRIM3D_TRIFAN, flags );
vb = (union fi *)intelExtendInlinePrimitive( intel, 4 * 6 );
/* initial vertex, left bottom */
vb[0].f = x0;
vb[1].f = y0;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s0;
vb[5].f = t0;
vb += 6;
/* right bottom */
vb[0].f = x1;
vb[1].f = y0;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s1;
vb[5].f = t0;
vb += 6;
/* right top */
vb[0].f = x1;
vb[1].f = y1;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s1;
vb[5].f = t1;
vb += 6;
/* left top */
vb[0].f = x0;
vb[1].f = y1;
vb[2].f = z;
vb[3].i = color;
vb[4].f = s0;
vb[5].f = t1;
if (intel->prim.flush)
intel->prim.flush(intel);
}
/**********************************************************************/
/* Initialization. */

View File

@@ -30,6 +30,8 @@
#include "mtypes.h"
#define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
_DD_NEW_TRI_UNFILLED | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
@@ -40,7 +42,23 @@
extern void intelInitTriFuncs( GLcontext *ctx );
extern void intelPrintRenderState( const char *msg, GLuint state );
extern void intelChooseRenderState( GLcontext *ctx );
extern void intelStartInlinePrimitive( struct intel_context *intel, GLuint prim, GLuint flags );
extern void intelWrapInlinePrimitive( struct intel_context *intel );
GLuint *intelExtendInlinePrimitive( struct intel_context *intel,
GLuint dwords );
void intel_meta_draw_quad(struct intel_context *intel,
GLfloat x0, GLfloat x1,
GLfloat y0, GLfloat y1,
GLfloat z,
GLuint color,
GLfloat s0, GLfloat s1,
GLfloat t0, GLfloat t1,
GLuint flags );
#endif

View File

@@ -32,6 +32,7 @@
#include "colormac.h"
#include "mtypes.h"
#include "program.h"
#include "teximage.h"
#include "swrast.h"
#include "s_blend.h"
#include "s_context.h"
@@ -368,6 +369,83 @@ _swrast_validate_blend_func( GLcontext *ctx, GLuint n,
}
/**
* Make sure we have texture image data for all the textures we may need
* for subsequent rendering.
*/
static void
_swrast_validate_texture_images(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint u;
if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) {
/* no textures enabled, or no way to validate images! */
return;
}
for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
ASSERT(texObj);
if (texObj) {
GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face;
for (face = 0; face < numFaces; face++) {
GLuint lvl;
for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
struct gl_texture_image *texImg = texObj->Image[face][lvl];
if (texImg && !texImg->Data) {
swrast->ValidateTextureImage(ctx, texObj, face, lvl);
ASSERT(texObj->Image[face][lvl]->Data);
}
}
}
}
}
}
}
/**
* Free the texture image data attached to all currently enabled
* textures. Meant to be called by device drivers when transitioning
* from software to hardware rendering.
*/
void
_swrast_eject_texture_images(GLcontext *ctx)
{
GLuint u;
if (!ctx->Texture._EnabledUnits) {
/* no textures enabled */
return;
}
for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
ASSERT(texObj);
if (texObj) {
GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face;
for (face = 0; face < numFaces; face++) {
GLuint lvl;
for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
struct gl_texture_image *texImg = texObj->Image[face][lvl];
if (texImg && texImg->Data) {
_mesa_free_texmemory(texImg->Data);
texImg->Data = NULL;
}
}
}
}
}
}
}
static void
_swrast_sleep( GLcontext *ctx, GLbitfield new_state )
{
@@ -452,6 +530,9 @@ _swrast_validate_derived( GLcontext *ctx )
if (swrast->NewState & _NEW_TEXTURE)
_swrast_update_texture_samplers( ctx );
if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM))
_swrast_validate_texture_images( ctx );
swrast->NewState = 0;
swrast->StateChanges = 0;
swrast->InvalidateState = _swrast_invalidate_state;

View File

@@ -226,6 +226,11 @@ typedef void (*swrast_tri_func)( GLcontext *ctx, const SWvertex *,
const SWvertex *, const SWvertex *);
typedef void (*validate_texture_image_func)(GLcontext *ctx,
struct gl_texture_object *texObj,
GLuint face, GLuint level);
/** \defgroup Bitmasks
* Bitmasks to indicate which rasterization options are enabled
* (RasterMask)
@@ -354,6 +359,8 @@ typedef struct
*/
GLchan *TexelBuffer;
validate_texture_image_func ValidateTextureImage;
} SWcontext;

View File

@@ -244,6 +244,10 @@ _swrast_copy_texsubimage3d(GLcontext *ctx,
GLint x, GLint y, GLsizei width, GLsizei height);
extern void
_swrast_eject_texture_images(GLcontext *ctx);
/**
* The driver interface for the software rasterizer.
* XXX this may go away.