merge of glsl-compiler-1 branch
[mesa.git] / src / mesa / drivers / dri / i915tex / intel_screen.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, 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 TUNGSTEN GRAPHICS 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
28 #include "glheader.h"
29 #include "context.h"
30 #include "framebuffer.h"
31 #include "matrix.h"
32 #include "renderbuffer.h"
33 #include "simple_list.h"
34 #include "utils.h"
35 #include "vblank.h"
36 #include "xmlpool.h"
37
38
39 #include "intel_screen.h"
40
41 #include "intel_buffers.h"
42 #include "intel_tex.h"
43 #include "intel_span.h"
44 #include "intel_tris.h"
45 #include "intel_ioctl.h"
46 #include "intel_fbo.h"
47
48 #include "i830_dri.h"
49 #include "dri_bufpool.h"
50 #include "intel_regions.h"
51 #include "intel_batchbuffer.h"
52
53 PUBLIC const char __driConfigOptions[] =
54 DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
55 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
56 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
57 DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
58 DRI_CONF_FORCE_S3TC_ENABLE(false)
59 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
60 DRI_CONF_SECTION_END DRI_CONF_END;
61 const GLuint __driNConfigOptions = 4;
62
63 #ifdef USE_NEW_INTERFACE
64 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
65 #endif /*USE_NEW_INTERFACE */
66
67 extern const struct dri_extension card_extensions[];
68
69 /**
70 * Map all the memory regions described by the screen.
71 * \return GL_TRUE if success, GL_FALSE if error.
72 */
73 GLboolean
74 intelMapScreenRegions(__DRIscreenPrivate * sPriv)
75 {
76 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
77
78 if (intelScreen->front.handle) {
79 if (drmMap(sPriv->fd,
80 intelScreen->front.handle,
81 intelScreen->front.size,
82 (drmAddress *) & intelScreen->front.map) != 0) {
83 _mesa_problem(NULL, "drmMap(frontbuffer) failed!");
84 return GL_FALSE;
85 }
86 }
87 else {
88 _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
89 }
90
91 if (0)
92 _mesa_printf("Back 0x%08x ", intelScreen->back.handle);
93 if (drmMap(sPriv->fd,
94 intelScreen->back.handle,
95 intelScreen->back.size,
96 (drmAddress *) & intelScreen->back.map) != 0) {
97 intelUnmapScreenRegions(intelScreen);
98 return GL_FALSE;
99 }
100
101 if (intelScreen->third.handle) {
102 if (0)
103 _mesa_printf("Third 0x%08x ", intelScreen->third.handle);
104 if (drmMap(sPriv->fd,
105 intelScreen->third.handle,
106 intelScreen->third.size,
107 (drmAddress *) & intelScreen->third.map) != 0) {
108 intelUnmapScreenRegions(intelScreen);
109 return GL_FALSE;
110 }
111 }
112
113 if (0)
114 _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);
115 if (drmMap(sPriv->fd,
116 intelScreen->depth.handle,
117 intelScreen->depth.size,
118 (drmAddress *) & intelScreen->depth.map) != 0) {
119 intelUnmapScreenRegions(intelScreen);
120 return GL_FALSE;
121 }
122
123 #if 0
124 _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
125 if (drmMap(sPriv->fd,
126 intelScreen->tex.handle,
127 intelScreen->tex.size,
128 (drmAddress *) & intelScreen->tex.map) != 0) {
129 intelUnmapScreenRegions(intelScreen);
130 return GL_FALSE;
131 }
132 #endif
133 if (0)
134 printf("Mappings: front: %p back: %p third: %p depth: %p tex: %p\n",
135 intelScreen->front.map,
136 intelScreen->back.map, intelScreen->third.map,
137 intelScreen->depth.map, intelScreen->tex.map);
138 return GL_TRUE;
139 }
140
141
142 static struct intel_region *
143 intel_recreate_static(intelScreenPrivate *intelScreen,
144 struct intel_region *region,
145 GLuint mem_type,
146 GLuint offset,
147 void *virtual,
148 GLuint cpp, GLuint pitch, GLuint height)
149 {
150 if (region) {
151 intel_region_update_static(intelScreen, region, mem_type, offset,
152 virtual, cpp, pitch, height);
153 } else {
154 region = intel_region_create_static(intelScreen, mem_type, offset,
155 virtual, cpp, pitch, height);
156 }
157 return region;
158 }
159
160
161 /* Create intel_region structs to describe the static front,back,depth
162 * buffers created by the xserver.
163 *
164 * Although FBO's mean we now no longer use these as render targets in
165 * all circumstances, they won't go away until the back and depth
166 * buffers become private, and the front and rotated buffers will
167 * remain even then.
168 *
169 * Note that these don't allocate video memory, just describe
170 * allocations alread made by the X server.
171 */
172 static void
173 intel_recreate_static_regions(intelScreenPrivate *intelScreen)
174 {
175 intelScreen->front_region =
176 intel_recreate_static(intelScreen,
177 intelScreen->front_region,
178 DRM_BO_FLAG_MEM_TT,
179 intelScreen->front.offset,
180 intelScreen->front.map,
181 intelScreen->cpp,
182 intelScreen->front.pitch / intelScreen->cpp,
183 intelScreen->height);
184
185 intelScreen->rotated_region =
186 intel_recreate_static(intelScreen,
187 intelScreen->rotated_region,
188 DRM_BO_FLAG_MEM_TT,
189 intelScreen->rotated.offset,
190 intelScreen->rotated.map,
191 intelScreen->cpp,
192 intelScreen->rotated.pitch /
193 intelScreen->cpp, intelScreen->height);
194
195
196 intelScreen->back_region =
197 intel_recreate_static(intelScreen,
198 intelScreen->back_region,
199 DRM_BO_FLAG_MEM_TT,
200 intelScreen->back.offset,
201 intelScreen->back.map,
202 intelScreen->cpp,
203 intelScreen->back.pitch / intelScreen->cpp,
204 intelScreen->height);
205
206 if (intelScreen->third.handle) {
207 intelScreen->third_region =
208 intel_recreate_static(intelScreen,
209 intelScreen->third_region,
210 DRM_BO_FLAG_MEM_TT,
211 intelScreen->third.offset,
212 intelScreen->third.map,
213 intelScreen->cpp,
214 intelScreen->third.pitch / intelScreen->cpp,
215 intelScreen->height);
216 }
217
218 /* Still assuming front.cpp == depth.cpp
219 */
220 intelScreen->depth_region =
221 intel_recreate_static(intelScreen,
222 intelScreen->depth_region,
223 DRM_BO_FLAG_MEM_TT,
224 intelScreen->depth.offset,
225 intelScreen->depth.map,
226 intelScreen->cpp,
227 intelScreen->depth.pitch / intelScreen->cpp,
228 intelScreen->height);
229 }
230
231 /**
232 * Use the information in the sarea to update the screen parameters
233 * related to screen rotation. Needs to be called locked.
234 */
235 void
236 intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
237 {
238 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
239
240 intelUnmapScreenRegions(intelScreen);
241 intelUpdateScreenFromSAREA(intelScreen, sarea);
242 if (!intelMapScreenRegions(sPriv)) {
243 fprintf(stderr, "ERROR Remapping screen regions!!!\n");
244 }
245 intel_recreate_static_regions(intelScreen);
246 }
247
248
249 void
250 intelUnmapScreenRegions(intelScreenPrivate * intelScreen)
251 {
252 #define REALLY_UNMAP 1
253 if (intelScreen->front.map) {
254 #if REALLY_UNMAP
255 if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0)
256 printf("drmUnmap front failed!\n");
257 #endif
258 intelScreen->front.map = NULL;
259 }
260 if (intelScreen->back.map) {
261 #if REALLY_UNMAP
262 if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0)
263 printf("drmUnmap back failed!\n");
264 #endif
265 intelScreen->back.map = NULL;
266 }
267 if (intelScreen->third.map) {
268 #if REALLY_UNMAP
269 if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0)
270 printf("drmUnmap third failed!\n");
271 #endif
272 intelScreen->third.map = NULL;
273 }
274 if (intelScreen->depth.map) {
275 #if REALLY_UNMAP
276 drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
277 intelScreen->depth.map = NULL;
278 #endif
279 }
280 if (intelScreen->tex.map) {
281 #if REALLY_UNMAP
282 drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
283 intelScreen->tex.map = NULL;
284 #endif
285 }
286 }
287
288
289 static void
290 intelPrintDRIInfo(intelScreenPrivate * intelScreen,
291 __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
292 {
293 fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
294 intelScreen->front.size, intelScreen->front.offset,
295 intelScreen->front.pitch);
296 fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n",
297 intelScreen->back.size, intelScreen->back.offset,
298 intelScreen->back.pitch);
299 fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n",
300 intelScreen->depth.size, intelScreen->depth.offset,
301 intelScreen->depth.pitch);
302 fprintf(stderr, "*** Rotated size: 0x%x offset: 0x%x pitch: %d\n",
303 intelScreen->rotated.size, intelScreen->rotated.offset,
304 intelScreen->rotated.pitch);
305 fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n",
306 intelScreen->tex.size, intelScreen->tex.offset);
307 fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
308 }
309
310
311 static void
312 intelPrintSAREA(const drmI830Sarea * sarea)
313 {
314 fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width,
315 sarea->height);
316 fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
317 fprintf(stderr,
318 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
319 sarea->front_offset, sarea->front_size,
320 (unsigned) sarea->front_handle);
321 fprintf(stderr,
322 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
323 sarea->back_offset, sarea->back_size,
324 (unsigned) sarea->back_handle);
325 fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
326 sarea->depth_offset, sarea->depth_size,
327 (unsigned) sarea->depth_handle);
328 fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
329 sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
330 fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
331 fprintf(stderr,
332 "SAREA: rotated offset: 0x%08x size: 0x%x\n",
333 sarea->rotated_offset, sarea->rotated_size);
334 fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch);
335 }
336
337
338 /**
339 * A number of the screen parameters are obtained/computed from
340 * information in the SAREA. This function updates those parameters.
341 */
342 void
343 intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
344 drmI830Sarea * sarea)
345 {
346 intelScreen->width = sarea->width;
347 intelScreen->height = sarea->height;
348
349 intelScreen->front.offset = sarea->front_offset;
350 intelScreen->front.pitch = sarea->pitch * intelScreen->cpp;
351 intelScreen->front.handle = sarea->front_handle;
352 intelScreen->front.size = sarea->front_size;
353
354 intelScreen->back.offset = sarea->back_offset;
355 intelScreen->back.pitch = sarea->pitch * intelScreen->cpp;
356 intelScreen->back.handle = sarea->back_handle;
357 intelScreen->back.size = sarea->back_size;
358
359 if (intelScreen->driScrnPriv->ddxMinor >= 8) {
360 intelScreen->third.offset = sarea->third_offset;
361 intelScreen->third.pitch = sarea->pitch * intelScreen->cpp;
362 intelScreen->third.handle = sarea->third_handle;
363 intelScreen->third.size = sarea->third_size;
364 }
365
366 intelScreen->depth.offset = sarea->depth_offset;
367 intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp;
368 intelScreen->depth.handle = sarea->depth_handle;
369 intelScreen->depth.size = sarea->depth_size;
370
371 intelScreen->tex.offset = sarea->tex_offset;
372 intelScreen->logTextureGranularity = sarea->log_tex_granularity;
373 intelScreen->tex.handle = sarea->tex_handle;
374 intelScreen->tex.size = sarea->tex_size;
375
376 intelScreen->rotated.offset = sarea->rotated_offset;
377 intelScreen->rotated.pitch = sarea->rotated_pitch * intelScreen->cpp;
378 intelScreen->rotated.size = sarea->rotated_size;
379 intelScreen->current_rotation = sarea->rotation;
380 matrix23Rotate(&intelScreen->rotMatrix,
381 sarea->width, sarea->height, sarea->rotation);
382 intelScreen->rotatedWidth = sarea->virtualX;
383 intelScreen->rotatedHeight = sarea->virtualY;
384
385 if (0)
386 intelPrintSAREA(sarea);
387 }
388
389
390 static GLboolean
391 intelInitDriver(__DRIscreenPrivate * sPriv)
392 {
393 intelScreenPrivate *intelScreen;
394 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
395 drmI830Sarea *sarea;
396 unsigned batchPoolSize = 1024*1024;
397
398 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
399 (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->
400 getProcAddress("glxEnableExtension"));
401 void *const psc = sPriv->psc->screenConfigs;
402
403 if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
404 fprintf(stderr,
405 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
406 return GL_FALSE;
407 }
408
409 /* Allocate the private area */
410 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
411 if (!intelScreen) {
412 fprintf(stderr, "\nERROR! Allocating private area failed\n");
413 return GL_FALSE;
414 }
415 /* parse information in __driConfigOptions */
416 driParseOptionInfo(&intelScreen->optionCache,
417 __driConfigOptions, __driNConfigOptions);
418
419 intelScreen->driScrnPriv = sPriv;
420 sPriv->private = (void *) intelScreen;
421 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
422 sarea = (drmI830Sarea *)
423 (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
424
425 intelScreen->maxBatchSize = BATCH_SZ;
426 intelScreen->deviceID = gDRIPriv->deviceID;
427 if (intelScreen->deviceID == PCI_CHIP_I865_G)
428 intelScreen->maxBatchSize = 4096;
429 batchPoolSize /= intelScreen->maxBatchSize;
430
431 intelScreen->mem = gDRIPriv->mem;
432 intelScreen->cpp = gDRIPriv->cpp;
433
434 switch (gDRIPriv->bitsPerPixel) {
435 case 16:
436 intelScreen->fbFormat = DV_PF_565;
437 break;
438 case 32:
439 intelScreen->fbFormat = DV_PF_8888;
440 break;
441 default:
442 exit(1);
443 break;
444 }
445
446 intelUpdateScreenFromSAREA(intelScreen, sarea);
447
448 if (!intelMapScreenRegions(sPriv)) {
449 fprintf(stderr, "\nERROR! mapping regions\n");
450 _mesa_free(intelScreen);
451 sPriv->private = NULL;
452 return GL_FALSE;
453 }
454
455 #if 0
456
457 /*
458 * FIXME: Remove this code and its references.
459 */
460
461 intelScreen->tex.offset = gDRIPriv->textureOffset;
462 intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
463 intelScreen->tex.handle = gDRIPriv->textures;
464 intelScreen->tex.size = gDRIPriv->textureSize;
465
466 #else
467 intelScreen->tex.offset = 0;
468 intelScreen->logTextureGranularity = 0;
469 intelScreen->tex.handle = 0;
470 intelScreen->tex.size = 0;
471 #endif
472
473 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
474
475 if (0)
476 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
477
478 intelScreen->drmMinor = sPriv->drmMinor;
479
480 /* Determine if IRQs are active? */
481 {
482 int ret;
483 drmI830GetParam gp;
484
485 gp.param = I830_PARAM_IRQ_ACTIVE;
486 gp.value = &intelScreen->irq_active;
487
488 ret = drmCommandWriteRead(sPriv->fd, DRM_I830_GETPARAM,
489 &gp, sizeof(gp));
490 if (ret) {
491 fprintf(stderr, "drmI830GetParam: %d\n", ret);
492 return GL_FALSE;
493 }
494 }
495
496 /* Determine if batchbuffers are allowed */
497 {
498 int ret;
499 drmI830GetParam gp;
500
501 gp.param = I830_PARAM_ALLOW_BATCHBUFFER;
502 gp.value = &intelScreen->allow_batchbuffer;
503
504 ret = drmCommandWriteRead(sPriv->fd, DRM_I830_GETPARAM,
505 &gp, sizeof(gp));
506 if (ret) {
507 fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret);
508 return GL_FALSE;
509 }
510 }
511
512 if (glx_enable_extension != NULL) {
513 (*glx_enable_extension) (psc, "GLX_SGI_swap_control");
514 (*glx_enable_extension) (psc, "GLX_SGI_video_sync");
515 (*glx_enable_extension) (psc, "GLX_MESA_swap_control");
516 (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage");
517 (*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
518 }
519
520 intelScreen->regionPool = driDRMPoolInit(sPriv->fd);
521
522 if (!intelScreen->regionPool)
523 return GL_FALSE;
524
525 intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
526
527 if (!intelScreen->staticPool)
528 return GL_FALSE;
529
530 intelScreen->texPool = intelScreen->regionPool;
531
532 intelScreen->batchPool = driBatchPoolInit(sPriv->fd,
533 DRM_BO_FLAG_EXE |
534 DRM_BO_FLAG_MEM_TT |
535 DRM_BO_FLAG_MEM_LOCAL,
536 intelScreen->maxBatchSize,
537 batchPoolSize, 5);
538 if (!intelScreen->batchPool) {
539 fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n");
540 return GL_FALSE;
541 }
542
543 intel_recreate_static_regions(intelScreen);
544
545 return GL_TRUE;
546 }
547
548
549 static void
550 intelDestroyScreen(__DRIscreenPrivate * sPriv)
551 {
552 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
553
554 intelUnmapScreenRegions(intelScreen);
555
556 driPoolTakeDown(intelScreen->regionPool);
557 driPoolTakeDown(intelScreen->staticPool);
558 driPoolTakeDown(intelScreen->batchPool);
559 FREE(intelScreen);
560 sPriv->private = NULL;
561 }
562
563
564 /**
565 * This is called when we need to set up GL rendering to a new X window.
566 */
567 static GLboolean
568 intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
569 __DRIdrawablePrivate * driDrawPriv,
570 const __GLcontextModes * mesaVis, GLboolean isPixmap)
571 {
572 intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
573
574 if (isPixmap) {
575 return GL_FALSE; /* not implemented */
576 }
577 else {
578 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
579 mesaVis->depthBits != 24);
580 GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
581
582 struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer);
583
584 if (!intel_fb)
585 return GL_FALSE;
586
587 _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
588
589 /* setup the hardware-based renderbuffers */
590 {
591 intel_fb->color_rb[0]
592 = intel_create_renderbuffer(rgbFormat,
593 screen->width, screen->height,
594 screen->front.offset,
595 screen->front.pitch,
596 screen->cpp,
597 screen->front.map);
598 intel_set_span_functions(&intel_fb->color_rb[0]->Base);
599 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
600 &intel_fb->color_rb[0]->Base);
601 }
602
603 if (mesaVis->doubleBufferMode) {
604 intel_fb->color_rb[1]
605 = intel_create_renderbuffer(rgbFormat,
606 screen->width, screen->height,
607 screen->back.offset,
608 screen->back.pitch,
609 screen->cpp,
610 screen->back.map);
611 intel_set_span_functions(&intel_fb->color_rb[1]->Base);
612 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
613 &intel_fb->color_rb[1]->Base);
614
615 if (screen->third.handle) {
616 struct gl_renderbuffer *tmp_rb = NULL;
617
618 intel_fb->color_rb[2]
619 = intel_create_renderbuffer(rgbFormat,
620 screen->width, screen->height,
621 screen->third.offset,
622 screen->third.pitch,
623 screen->cpp,
624 screen->third.map);
625 intel_set_span_functions(&intel_fb->color_rb[2]->Base);
626 _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
627 }
628 }
629
630 if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
631 /* combined depth/stencil buffer */
632 struct intel_renderbuffer *depthStencilRb
633 = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT,
634 screen->width, screen->height,
635 screen->depth.offset,
636 screen->depth.pitch,
637 screen->cpp, /* 4! */
638 screen->depth.map);
639 intel_set_span_functions(&depthStencilRb->Base);
640 /* note: bind RB to two attachment points */
641 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
642 &depthStencilRb->Base);
643 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL,
644 &depthStencilRb->Base);
645 }
646 else if (mesaVis->depthBits == 16) {
647 /* just 16-bit depth buffer, no hw stencil */
648 struct intel_renderbuffer *depthRb
649 = intel_create_renderbuffer(GL_DEPTH_COMPONENT16,
650 screen->width, screen->height,
651 screen->depth.offset,
652 screen->depth.pitch,
653 screen->cpp, /* 2! */
654 screen->depth.map);
655 intel_set_span_functions(&depthRb->Base);
656 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
657 }
658
659 /* now add any/all software-based renderbuffers we may need */
660 _mesa_add_soft_renderbuffers(&intel_fb->Base,
661 GL_FALSE, /* never sw color */
662 GL_FALSE, /* never sw depth */
663 swStencil, mesaVis->accumRedBits > 0,
664 GL_FALSE, /* never sw alpha */
665 GL_FALSE /* never sw aux */ );
666 driDrawPriv->driverPrivate = (void *) intel_fb;
667
668 return GL_TRUE;
669 }
670 }
671
672 static void
673 intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
674 {
675 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
676 }
677
678
679 /**
680 * Get information about previous buffer swaps.
681 */
682 static int
683 intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
684 {
685 struct intel_framebuffer *intel_fb;
686
687 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
688 || (sInfo == NULL)) {
689 return -1;
690 }
691
692 intel_fb = dPriv->driverPrivate;
693 sInfo->swap_count = intel_fb->swap_count;
694 sInfo->swap_ust = intel_fb->swap_ust;
695 sInfo->swap_missed_count = intel_fb->swap_missed_count;
696
697 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
698 ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust)
699 : 0.0;
700
701 return 0;
702 }
703
704
705 /* There are probably better ways to do this, such as an
706 * init-designated function to register chipids and createcontext
707 * functions.
708 */
709 extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
710 __DRIcontextPrivate * driContextPriv,
711 void *sharedContextPrivate);
712
713 extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
714 __DRIcontextPrivate * driContextPriv,
715 void *sharedContextPrivate);
716
717
718
719
720 static GLboolean
721 intelCreateContext(const __GLcontextModes * mesaVis,
722 __DRIcontextPrivate * driContextPriv,
723 void *sharedContextPrivate)
724 {
725 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
726 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
727
728 switch (intelScreen->deviceID) {
729 /* Don't deal with i830 until texture work complete:
730 */
731 case PCI_CHIP_845_G:
732 case PCI_CHIP_I830_M:
733 case PCI_CHIP_I855_GM:
734 case PCI_CHIP_I865_G:
735 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
736
737 case PCI_CHIP_I915_G:
738 case PCI_CHIP_I915_GM:
739 case PCI_CHIP_I945_G:
740 case PCI_CHIP_I945_GM:
741 return i915CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
742
743 default:
744 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
745 return GL_FALSE;
746 }
747 }
748
749
750 static const struct __DriverAPIRec intelAPI = {
751 .InitDriver = intelInitDriver,
752 .DestroyScreen = intelDestroyScreen,
753 .CreateContext = intelCreateContext,
754 .DestroyContext = intelDestroyContext,
755 .CreateBuffer = intelCreateBuffer,
756 .DestroyBuffer = intelDestroyBuffer,
757 .SwapBuffers = intelSwapBuffers,
758 .MakeCurrent = intelMakeCurrent,
759 .UnbindContext = intelUnbindContext,
760 .GetSwapInfo = intelGetSwapInfo,
761 .GetMSC = driGetMSC32,
762 .WaitForMSC = driWaitForMSC32,
763 .WaitForSBC = NULL,
764 .SwapBuffersMSC = NULL,
765 .CopySubBuffer = intelCopySubBuffer
766 };
767
768
769 static __GLcontextModes *
770 intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
771 unsigned stencil_bits, GLboolean have_back_buffer)
772 {
773 __GLcontextModes *modes;
774 __GLcontextModes *m;
775 unsigned num_modes;
776 unsigned depth_buffer_factor;
777 unsigned back_buffer_factor;
778 GLenum fb_format;
779 GLenum fb_type;
780
781 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
782 * support pageflipping at all.
783 */
784 static const GLenum back_buffer_modes[] = {
785 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
786 };
787
788 u_int8_t depth_bits_array[3];
789 u_int8_t stencil_bits_array[3];
790
791
792 depth_bits_array[0] = 0;
793 depth_bits_array[1] = depth_bits;
794 depth_bits_array[2] = depth_bits;
795
796 /* Just like with the accumulation buffer, always provide some modes
797 * with a stencil buffer. It will be a sw fallback, but some apps won't
798 * care about that.
799 */
800 stencil_bits_array[0] = 0;
801 stencil_bits_array[1] = 0;
802 if (depth_bits == 24)
803 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
804
805 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
806
807 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
808 back_buffer_factor = (have_back_buffer) ? 3 : 1;
809
810 num_modes = depth_buffer_factor * back_buffer_factor * 4;
811
812 if (pixel_bits == 16) {
813 fb_format = GL_RGB;
814 fb_type = GL_UNSIGNED_SHORT_5_6_5;
815 }
816 else {
817 fb_format = GL_BGRA;
818 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
819 }
820
821 modes =
822 (*dri_interface->createContextModes) (num_modes,
823 sizeof(__GLcontextModes));
824 m = modes;
825 if (!driFillInModes(&m, fb_format, fb_type,
826 depth_bits_array, stencil_bits_array,
827 depth_buffer_factor, back_buffer_modes,
828 back_buffer_factor, GLX_TRUE_COLOR)) {
829 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
830 __LINE__);
831 return NULL;
832 }
833 if (!driFillInModes(&m, fb_format, fb_type,
834 depth_bits_array, stencil_bits_array,
835 depth_buffer_factor, back_buffer_modes,
836 back_buffer_factor, GLX_DIRECT_COLOR)) {
837 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
838 __LINE__);
839 return NULL;
840 }
841
842 /* Mark the visual as slow if there are "fake" stencil bits.
843 */
844 for (m = modes; m != NULL; m = m->next) {
845 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
846 m->visualRating = GLX_SLOW_CONFIG;
847 }
848 }
849
850 return modes;
851 }
852
853
854 /**
855 * This is the bootstrap function for the driver. libGL supplies all of the
856 * requisite information about the system, and the driver initializes itself.
857 * This routine also fills in the linked list pointed to by \c driver_modes
858 * with the \c __GLcontextModes that the driver can support for windows or
859 * pbuffers.
860 *
861 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
862 * failure.
863 */
864 PUBLIC void *
865 __driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
866 __DRIscreen * psc,
867 const __GLcontextModes * modes,
868 const __DRIversion * ddx_version,
869 const __DRIversion * dri_version,
870 const __DRIversion * drm_version,
871 const __DRIframebuffer * frame_buffer,
872 drmAddress pSAREA, int fd,
873 int internal_api_version,
874 const __DRIinterfaceMethods * interface,
875 __GLcontextModes ** driver_modes)
876 {
877 __DRIscreenPrivate *psp;
878 static const __DRIversion ddx_expected = { 1, 5, 0 };
879 static const __DRIversion dri_expected = { 4, 0, 0 };
880 static const __DRIversion drm_expected = { 1, 7, 0 };
881
882 dri_interface = interface;
883
884 if (!driCheckDriDdxDrmVersions2("i915",
885 dri_version, &dri_expected,
886 ddx_version, &ddx_expected,
887 drm_version, &drm_expected)) {
888 return NULL;
889 }
890
891 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
892 ddx_version, dri_version, drm_version,
893 frame_buffer, pSAREA, fd,
894 internal_api_version, &intelAPI);
895 if (psp != NULL) {
896 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
897 *driver_modes = intelFillInModes(dri_priv->cpp * 8,
898 (dri_priv->cpp == 2) ? 16 : 24,
899 (dri_priv->cpp == 2) ? 0 : 8, 1);
900
901 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
902 * enable the extensions. It just makes sure that all the dispatch offsets for all
903 * the extensions that *might* be enables are known. This is needed because the
904 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
905 * enable the extensions until we have a context pointer.
906 *
907 * Hello chicken. Hello egg. How are you two today?
908 */
909 driInitExtensions(NULL, card_extensions, GL_FALSE);
910 }
911
912 return (void *) psp;
913 }
914
915 struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
916 {
917 /*
918 * This should probably change to have the screen allocate a dummy
919 * context at screen creation. For now just use the current context.
920 */
921
922 GET_CURRENT_CONTEXT(ctx);
923 if (ctx == NULL) {
924 _mesa_problem(NULL, "No current context in intelScreenContext\n");
925 return NULL;
926 }
927 return intel_context(ctx);
928 }
929