Merge branch 'master' into r500test
[mesa.git] / src / mesa / drivers / dri / i810 / i810screen.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sub license, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810screen.c,v 1.2 2002/10/30 12:51:33 alanh Exp $ */
28
29 /*
30 * Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 *
33 */
34
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "context.h"
39 #include "framebuffer.h"
40 #include "fbobject.h"
41 #include "matrix.h"
42 #include "renderbuffer.h"
43 #include "simple_list.h"
44 #include "utils.h"
45
46 #include "i810screen.h"
47 #include "i810_dri.h"
48
49 #include "i810state.h"
50 #include "i810tex.h"
51 #include "i810span.h"
52 #include "i810tris.h"
53 #include "i810ioctl.h"
54
55 #include "GL/internal/dri_interface.h"
56
57 extern const struct dri_extension card_extensions[];
58
59 static const __DRIconfig **
60 i810FillInModes( __DRIscreenPrivate *psp,
61 unsigned pixel_bits, unsigned depth_bits,
62 unsigned stencil_bits, GLboolean have_back_buffer )
63 {
64 __DRIconfig **configs;
65 __GLcontextModes * m;
66 unsigned depth_buffer_factor;
67 unsigned back_buffer_factor;
68 unsigned i;
69
70 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
71 * enough to add support. Basically, if a context is created with an
72 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
73 * will never be used.
74 */
75 static const GLenum back_buffer_modes[] = {
76 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
77 };
78
79 u_int8_t depth_bits_array[2];
80 u_int8_t stencil_bits_array[2];
81
82 depth_bits_array[0] = depth_bits;
83 depth_bits_array[1] = depth_bits;
84
85 /* Just like with the accumulation buffer, always provide some modes
86 * with a stencil buffer. It will be a sw fallback, but some apps won't
87 * care about that.
88 */
89 stencil_bits_array[0] = 0;
90 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
91
92 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
93 back_buffer_factor = (have_back_buffer) ? 2 : 1;
94
95 configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
96 depth_bits_array, stencil_bits_array,
97 depth_buffer_factor,
98 back_buffer_modes, back_buffer_factor);
99 if (configs == NULL) {
100 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
101 __func__, __LINE__ );
102 return NULL;
103 }
104
105 /* Mark the visual as slow if there are "fake" stencil bits.
106 */
107 for (i = 0; configs[i]; i++) {
108 m = &configs[i]->modes;
109 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
110 m->visualRating = GLX_SLOW_CONFIG;
111 }
112 }
113
114 return (const __DRIconfig **) configs;
115 }
116
117
118 /* static int i810_malloc_proxy_buf(drmBufMapPtr buffers) */
119 /* { */
120 /* char *buffer; */
121 /* drmBufPtr buf; */
122 /* int i; */
123
124 /* buffer = CALLOC(I810_DMA_BUF_SZ); */
125 /* if(buffer == NULL) return -1; */
126 /* for(i = 0; i < I810_DMA_BUF_NR; i++) { */
127 /* buf = &(buffers->list[i]); */
128 /* buf->address = (drmAddress)buffer; */
129 /* } */
130 /* return 0; */
131 /* } */
132
133 static drmBufMapPtr i810_create_empty_buffers(void)
134 {
135 drmBufMapPtr retval;
136
137 retval = (drmBufMapPtr)ALIGN_MALLOC(sizeof(drmBufMap), 32);
138 if(retval == NULL) return NULL;
139 memset(retval, 0, sizeof(drmBufMap));
140 retval->list = (drmBufPtr)ALIGN_MALLOC(sizeof(drmBuf) * I810_DMA_BUF_NR, 32);
141 if(retval->list == NULL) {
142 ALIGN_FREE(retval);
143 return NULL;
144 }
145 memset(retval->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
146 return retval;
147 }
148
149
150 static const __DRIconfig **
151 i810InitScreen(__DRIscreen *sPriv)
152 {
153 static const __DRIversion ddx_expected = { 1, 0, 0 };
154 static const __DRIversion dri_expected = { 4, 0, 0 };
155 static const __DRIversion drm_expected = { 1, 2, 0 };
156 i810ScreenPrivate *i810Screen;
157 I810DRIPtr gDRIPriv = (I810DRIPtr)sPriv->pDevPriv;
158
159 if ( ! driCheckDriDdxDrmVersions2( "i810",
160 &sPriv->dri_version, & dri_expected,
161 &sPriv->ddx_version, & ddx_expected,
162 &sPriv->drm_version, & drm_expected ) ) {
163 return NULL;
164 }
165
166 driInitExtensions( NULL, card_extensions, GL_TRUE );
167
168 if (sPriv->devPrivSize != sizeof(I810DRIRec)) {
169 fprintf(stderr,"\nERROR! sizeof(I810DRIRec) does not match passed size from device driver\n");
170 return GL_FALSE;
171 }
172
173 /* Allocate the private area */
174 i810Screen = (i810ScreenPrivate *)CALLOC(sizeof(i810ScreenPrivate));
175 if (!i810Screen) {
176 __driUtilMessage("i810InitDriver: alloc i810ScreenPrivate struct failed");
177 return GL_FALSE;
178 }
179
180 i810Screen->driScrnPriv = sPriv;
181 sPriv->private = (void *)i810Screen;
182
183 i810Screen->deviceID=gDRIPriv->deviceID;
184 i810Screen->width=gDRIPriv->width;
185 i810Screen->height=gDRIPriv->height;
186 i810Screen->mem=gDRIPriv->mem;
187 i810Screen->cpp=gDRIPriv->cpp;
188 i810Screen->fbStride=gDRIPriv->fbStride;
189 i810Screen->fbOffset=gDRIPriv->fbOffset;
190
191 if (gDRIPriv->bitsPerPixel == 15)
192 i810Screen->fbFormat = DV_PF_555;
193 else
194 i810Screen->fbFormat = DV_PF_565;
195
196 i810Screen->backOffset=gDRIPriv->backOffset;
197 i810Screen->depthOffset=gDRIPriv->depthOffset;
198 i810Screen->backPitch = gDRIPriv->auxPitch;
199 i810Screen->backPitchBits = gDRIPriv->auxPitchBits;
200 i810Screen->textureOffset=gDRIPriv->textureOffset;
201 i810Screen->textureSize=gDRIPriv->textureSize;
202 i810Screen->logTextureGranularity = gDRIPriv->logTextureGranularity;
203
204 i810Screen->bufs = i810_create_empty_buffers();
205 if (i810Screen->bufs == NULL) {
206 __driUtilMessage("i810InitDriver: i810_create_empty_buffers() failed");
207 FREE(i810Screen);
208 return GL_FALSE;
209 }
210
211 i810Screen->back.handle = gDRIPriv->backbuffer;
212 i810Screen->back.size = gDRIPriv->backbufferSize;
213
214 if (drmMap(sPriv->fd,
215 i810Screen->back.handle,
216 i810Screen->back.size,
217 (drmAddress *)&i810Screen->back.map) != 0) {
218 FREE(i810Screen);
219 sPriv->private = NULL;
220 __driUtilMessage("i810InitDriver: drmMap failed");
221 return GL_FALSE;
222 }
223
224 i810Screen->depth.handle = gDRIPriv->depthbuffer;
225 i810Screen->depth.size = gDRIPriv->depthbufferSize;
226
227 if (drmMap(sPriv->fd,
228 i810Screen->depth.handle,
229 i810Screen->depth.size,
230 (drmAddress *)&i810Screen->depth.map) != 0) {
231 drmUnmap(i810Screen->back.map, i810Screen->back.size);
232 FREE(i810Screen);
233 sPriv->private = NULL;
234 __driUtilMessage("i810InitDriver: drmMap (2) failed");
235 return GL_FALSE;
236 }
237
238 i810Screen->tex.handle = gDRIPriv->textures;
239 i810Screen->tex.size = gDRIPriv->textureSize;
240
241 if (drmMap(sPriv->fd,
242 i810Screen->tex.handle,
243 i810Screen->tex.size,
244 (drmAddress *)&i810Screen->tex.map) != 0) {
245 drmUnmap(i810Screen->back.map, i810Screen->back.size);
246 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
247 FREE(i810Screen);
248 sPriv->private = NULL;
249 __driUtilMessage("i810InitDriver: drmMap (3) failed");
250 return GL_FALSE;
251 }
252
253 i810Screen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
254
255 return i810FillInModes(sPriv, 16, 16, 0, 1);
256 }
257
258 static void
259 i810DestroyScreen(__DRIscreenPrivate *sPriv)
260 {
261 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
262
263 /* Need to unmap all the bufs and maps here:
264 */
265 drmUnmap(i810Screen->back.map, i810Screen->back.size);
266 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
267 drmUnmap(i810Screen->tex.map, i810Screen->tex.size);
268
269 FREE(i810Screen);
270 sPriv->private = NULL;
271 }
272
273
274 /**
275 * Create a buffer which corresponds to the window.
276 */
277 static GLboolean
278 i810CreateBuffer( __DRIscreenPrivate *driScrnPriv,
279 __DRIdrawablePrivate *driDrawPriv,
280 const __GLcontextModes *mesaVis,
281 GLboolean isPixmap )
282 {
283 i810ScreenPrivate *screen = (i810ScreenPrivate *) driScrnPriv->private;
284
285 if (isPixmap) {
286 return GL_FALSE; /* not implemented */
287 }
288 else {
289 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
290
291 {
292 driRenderbuffer *frontRb
293 = driNewRenderbuffer(GL_RGBA,
294 driScrnPriv->pFB,
295 screen->cpp,
296 /*screen->frontOffset*/0, screen->backPitch,
297 driDrawPriv);
298 i810SetSpanFunctions(frontRb, mesaVis);
299 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
300 }
301
302 if (mesaVis->doubleBufferMode) {
303 driRenderbuffer *backRb
304 = driNewRenderbuffer(GL_RGBA,
305 screen->back.map,
306 screen->cpp,
307 screen->backOffset, screen->backPitch,
308 driDrawPriv);
309 i810SetSpanFunctions(backRb, mesaVis);
310 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
311 }
312
313 if (mesaVis->depthBits == 16) {
314 driRenderbuffer *depthRb
315 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
316 screen->depth.map,
317 screen->cpp,
318 screen->depthOffset, screen->backPitch,
319 driDrawPriv);
320 i810SetSpanFunctions(depthRb, mesaVis);
321 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
322 }
323
324 _mesa_add_soft_renderbuffers(fb,
325 GL_FALSE, /* color */
326 GL_FALSE, /* depth */
327 mesaVis->stencilBits > 0,
328 mesaVis->accumRedBits > 0,
329 GL_FALSE, /* alpha */
330 GL_FALSE /* aux */);
331 driDrawPriv->driverPrivate = (void *) fb;
332
333 return (driDrawPriv->driverPrivate != NULL);
334 }
335 }
336
337
338 static void
339 i810DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
340 {
341 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
342 }
343
344 const struct __DriverAPIRec driDriverAPI = {
345 .InitScreen = i810InitScreen,
346 .DestroyScreen = i810DestroyScreen,
347 .CreateContext = i810CreateContext,
348 .DestroyContext = i810DestroyContext,
349 .CreateBuffer = i810CreateBuffer,
350 .DestroyBuffer = i810DestroyBuffer,
351 .SwapBuffers = i810SwapBuffers,
352 .MakeCurrent = i810MakeCurrent,
353 .UnbindContext = i810UnbindContext,
354 .GetSwapInfo = NULL,
355 .GetDrawableMSC = NULL,
356 .WaitForMSC = NULL,
357 .WaitForSBC = NULL,
358 .SwapBuffersMSC = NULL
359 };