8b8eeb77aa3053c3a1fca1c5269850c4557c13ed
[mesa.git] / src / mesa / drivers / dri / intel / 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_ioctl.h"
45 #include "intel_fbo.h"
46 #include "intel_chipset.h"
47
48 #include "i915_drm.h"
49 #include "i830_dri.h"
50 #include "intel_regions.h"
51 #include "intel_batchbuffer.h"
52 #include "intel_bufmgr_ttm.h"
53
54 PUBLIC const char __driConfigOptions[] =
55 DRI_CONF_BEGIN
56 DRI_CONF_SECTION_PERFORMANCE
57 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
58 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
59 DRI_CONF_SECTION_END
60 DRI_CONF_SECTION_QUALITY
61 DRI_CONF_FORCE_S3TC_ENABLE(false)
62 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
63 DRI_CONF_SECTION_END
64 DRI_CONF_SECTION_DEBUG
65 DRI_CONF_NO_RAST(false)
66 DRI_CONF_SECTION_END
67 DRI_CONF_END;
68
69 const GLuint __driNConfigOptions = 5;
70
71 #ifdef USE_NEW_INTERFACE
72 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
73 #endif /*USE_NEW_INTERFACE */
74
75 /**
76 * Map all the memory regions described by the screen.
77 * \return GL_TRUE if success, GL_FALSE if error.
78 */
79 GLboolean
80 intelMapScreenRegions(__DRIscreenPrivate * sPriv)
81 {
82 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
83
84 if (intelScreen->front.handle) {
85 if (drmMap(sPriv->fd,
86 intelScreen->front.handle,
87 intelScreen->front.size,
88 (drmAddress *) & intelScreen->front.map) != 0) {
89 _mesa_problem(NULL, "drmMap(frontbuffer) failed!");
90 return GL_FALSE;
91 }
92 }
93 else {
94 _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
95 }
96
97 if (0)
98 _mesa_printf("Back 0x%08x ", intelScreen->back.handle);
99 if (drmMap(sPriv->fd,
100 intelScreen->back.handle,
101 intelScreen->back.size,
102 (drmAddress *) & intelScreen->back.map) != 0) {
103 intelUnmapScreenRegions(intelScreen);
104 return GL_FALSE;
105 }
106
107 if (intelScreen->third.handle) {
108 if (0)
109 _mesa_printf("Third 0x%08x ", intelScreen->third.handle);
110 if (drmMap(sPriv->fd,
111 intelScreen->third.handle,
112 intelScreen->third.size,
113 (drmAddress *) & intelScreen->third.map) != 0) {
114 intelUnmapScreenRegions(intelScreen);
115 return GL_FALSE;
116 }
117 }
118
119 if (0)
120 _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);
121 if (drmMap(sPriv->fd,
122 intelScreen->depth.handle,
123 intelScreen->depth.size,
124 (drmAddress *) & intelScreen->depth.map) != 0) {
125 intelUnmapScreenRegions(intelScreen);
126 return GL_FALSE;
127 }
128
129 if (0)
130 _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
131 if (intelScreen->tex.size != 0) {
132 if (drmMap(sPriv->fd,
133 intelScreen->tex.handle,
134 intelScreen->tex.size,
135 (drmAddress *) & intelScreen->tex.map) != 0) {
136 intelUnmapScreenRegions(intelScreen);
137 return GL_FALSE;
138 }
139 }
140
141 if (0)
142 printf("Mappings: front: %p back: %p third: %p depth: %p tex: %p\n",
143 intelScreen->front.map,
144 intelScreen->back.map, intelScreen->third.map,
145 intelScreen->depth.map, intelScreen->tex.map);
146 return GL_TRUE;
147 }
148
149 void
150 intelUnmapScreenRegions(intelScreenPrivate * intelScreen)
151 {
152 #define REALLY_UNMAP 1
153 if (intelScreen->front.map) {
154 #if REALLY_UNMAP
155 if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0)
156 printf("drmUnmap front failed!\n");
157 #endif
158 intelScreen->front.map = NULL;
159 }
160 if (intelScreen->back.map) {
161 #if REALLY_UNMAP
162 if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0)
163 printf("drmUnmap back failed!\n");
164 #endif
165 intelScreen->back.map = NULL;
166 }
167 if (intelScreen->third.map) {
168 #if REALLY_UNMAP
169 if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0)
170 printf("drmUnmap third failed!\n");
171 #endif
172 intelScreen->third.map = NULL;
173 }
174 if (intelScreen->depth.map) {
175 #if REALLY_UNMAP
176 drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
177 intelScreen->depth.map = NULL;
178 #endif
179 }
180 if (intelScreen->tex.map) {
181 #if REALLY_UNMAP
182 drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
183 intelScreen->tex.map = NULL;
184 #endif
185 }
186 }
187
188
189 static void
190 intelPrintDRIInfo(intelScreenPrivate * intelScreen,
191 __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
192 {
193 fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
194 intelScreen->front.size, intelScreen->front.offset,
195 intelScreen->pitch);
196 fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n",
197 intelScreen->back.size, intelScreen->back.offset,
198 intelScreen->pitch);
199 fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n",
200 intelScreen->depth.size, intelScreen->depth.offset,
201 intelScreen->pitch);
202 fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n",
203 intelScreen->tex.size, intelScreen->tex.offset);
204 fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
205 }
206
207
208 static void
209 intelPrintSAREA(const struct drm_i915_sarea * sarea)
210 {
211 fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width,
212 sarea->height);
213 fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
214 fprintf(stderr,
215 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
216 sarea->front_offset, sarea->front_size,
217 (unsigned) sarea->front_handle);
218 fprintf(stderr,
219 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
220 sarea->back_offset, sarea->back_size,
221 (unsigned) sarea->back_handle);
222 fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
223 sarea->depth_offset, sarea->depth_size,
224 (unsigned) sarea->depth_handle);
225 fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
226 sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
227 }
228
229
230 /**
231 * A number of the screen parameters are obtained/computed from
232 * information in the SAREA. This function updates those parameters.
233 */
234 void
235 intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
236 struct drm_i915_sarea * sarea)
237 {
238 intelScreen->width = sarea->width;
239 intelScreen->height = sarea->height;
240 intelScreen->pitch = sarea->pitch;
241
242 intelScreen->front.offset = sarea->front_offset;
243 intelScreen->front.handle = sarea->front_handle;
244 intelScreen->front.size = sarea->front_size;
245 intelScreen->front.tiled = sarea->front_tiled;
246
247 intelScreen->back.offset = sarea->back_offset;
248 intelScreen->back.handle = sarea->back_handle;
249 intelScreen->back.size = sarea->back_size;
250 intelScreen->back.tiled = sarea->back_tiled;
251
252 if (intelScreen->driScrnPriv->ddx_version.minor >= 8) {
253 intelScreen->third.offset = sarea->third_offset;
254 intelScreen->third.handle = sarea->third_handle;
255 intelScreen->third.size = sarea->third_size;
256 intelScreen->third.tiled = sarea->third_tiled;
257 }
258
259 intelScreen->depth.offset = sarea->depth_offset;
260 intelScreen->depth.handle = sarea->depth_handle;
261 intelScreen->depth.size = sarea->depth_size;
262 intelScreen->depth.tiled = sarea->depth_tiled;
263
264 if (intelScreen->driScrnPriv->ddx_version.minor >= 9) {
265 intelScreen->front.bo_handle = sarea->front_bo_handle;
266 intelScreen->back.bo_handle = sarea->back_bo_handle;
267 intelScreen->third.bo_handle = sarea->third_bo_handle;
268 intelScreen->depth.bo_handle = sarea->depth_bo_handle;
269 } else {
270 intelScreen->front.bo_handle = -1;
271 intelScreen->back.bo_handle = -1;
272 intelScreen->third.bo_handle = -1;
273 intelScreen->depth.bo_handle = -1;
274 }
275
276 intelScreen->tex.offset = sarea->tex_offset;
277 intelScreen->logTextureGranularity = sarea->log_tex_granularity;
278 intelScreen->tex.handle = sarea->tex_handle;
279 intelScreen->tex.size = sarea->tex_size;
280
281 if (0)
282 intelPrintSAREA(sarea);
283 }
284
285 static void
286 intelHandleDrawableConfig(__DRIdrawablePrivate *dPriv,
287 __DRIDrawableConfigEvent *event)
288 {
289 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
290 struct intel_region *region = NULL;
291 struct intel_renderbuffer *rb, *depth_rb, *stencil_rb;
292 struct intel_context *intel = dPriv->driContextPriv->driverPrivate;
293 int cpp = intel->ctx.Visual.rgbBits / 8;
294 GLuint pitch = ((cpp * dPriv->w + 63) & ~63) / cpp;
295
296 rb = intel_fb->color_rb[1];
297 if (rb) {
298 region = intel_region_alloc(intel, cpp, pitch, dPriv->h);
299 intel_renderbuffer_set_region(rb, region);
300 }
301
302 rb = intel_fb->color_rb[2];
303 if (rb) {
304 region = intel_region_alloc(intel, cpp, pitch, dPriv->h);
305 intel_renderbuffer_set_region(rb, region);
306 }
307
308 depth_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
309 stencil_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
310 if (depth_rb || stencil_rb)
311 region = intel_region_alloc(intel, cpp, pitch, dPriv->h);
312 if (depth_rb)
313 intel_renderbuffer_set_region(depth_rb, region);
314 if (stencil_rb)
315 intel_renderbuffer_set_region(stencil_rb, region);
316
317 /* FIXME: Tell the X server about the regions we just allocated and
318 * attached. */
319 }
320
321 #define BUFFER_FLAG_TILED 0x0100
322
323 static void
324 intelHandleBufferAttach(__DRIdrawablePrivate *dPriv,
325 __DRIBufferAttachEvent *ba)
326 {
327 struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
328 struct intel_renderbuffer *rb;
329 struct intel_region *region;
330 struct intel_context *intel = dPriv->driContextPriv->driverPrivate;
331 GLuint tiled;
332
333 switch (ba->buffer.attachment) {
334 case DRI_DRAWABLE_BUFFER_FRONT_LEFT:
335 rb = intel_fb->color_rb[0];
336 break;
337
338 case DRI_DRAWABLE_BUFFER_BACK_LEFT:
339 rb = intel_fb->color_rb[0];
340 break;
341
342 case DRI_DRAWABLE_BUFFER_DEPTH:
343 rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);
344 break;
345
346 case DRI_DRAWABLE_BUFFER_STENCIL:
347 rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL);
348 break;
349
350 case DRI_DRAWABLE_BUFFER_ACCUM:
351 default:
352 fprintf(stderr, "unhandled buffer attach event, attacment type %d\n",
353 ba->buffer.attachment);
354 return;
355 }
356
357 #if 0
358 /* FIXME: Add this so we can filter out when the X server sends us
359 * attachment events for the buffers we just allocated. Need to
360 * get the BO handle for a render buffer. */
361 if (intel_renderbuffer_get_region_handle(rb) == ba->buffer.handle)
362 return;
363 #endif
364
365 tiled = (ba->buffer.flags & BUFFER_FLAG_TILED) > 0;
366 region = intel_region_alloc_for_handle(intel, ba->buffer.cpp,
367 ba->buffer.pitch / ba->buffer.cpp,
368 dPriv->h, tiled,
369 ba->buffer.handle);
370
371 intel_renderbuffer_set_region(rb, region);
372 }
373
374 static void
375 intelUpdateBuffer(__DRIdrawablePrivate *dPriv, unsigned int *event)
376 {
377 switch (DRI2_EVENT_TYPE(*event)) {
378 case DRI2_EVENT_DRAWABLE_CONFIG:
379 /* flush all current regions, allocate new ones, except front buffer */
380 intelHandleDrawableConfig(dPriv, (__DRIDrawableConfigEvent *) event);
381 break;
382
383 case DRI2_EVENT_BUFFER_ATTACH:
384 /* attach buffer if different from what we have */
385 intelHandleBufferAttach(dPriv, (__DRIBufferAttachEvent *) event);
386 break;
387 }
388 }
389
390 static const __DRItexOffsetExtension intelTexOffsetExtension = {
391 { __DRI_TEX_OFFSET },
392 intelSetTexOffset,
393 };
394
395 static const __DRItexBufferExtension intelTexBufferExtension = {
396 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
397 intelSetTexBuffer,
398 };
399
400 static const __DRIextension *intelExtensions[] = {
401 &driReadDrawableExtension,
402 &driCopySubBufferExtension.base,
403 &driSwapControlExtension.base,
404 &driFrameTrackingExtension.base,
405 &driMediaStreamCounterExtension.base,
406 &intelTexOffsetExtension.base,
407 &intelTexBufferExtension.base,
408 NULL
409 };
410
411 static GLboolean
412 intel_get_param(__DRIscreenPrivate *psp, int param, int *value)
413 {
414 int ret;
415 struct drm_i915_getparam gp;
416
417 gp.param = param;
418 gp.value = value;
419
420 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
421 if (ret) {
422 fprintf(stderr, "drm_i915_getparam: %d\n", ret);
423 return GL_FALSE;
424 }
425
426 return GL_TRUE;
427 }
428
429 static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
430 {
431 intelScreenPrivate *intelScreen;
432 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
433 struct drm_i915_sarea *sarea;
434
435 if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
436 fprintf(stderr,
437 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
438 return GL_FALSE;
439 }
440
441 /* Allocate the private area */
442 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
443 if (!intelScreen) {
444 fprintf(stderr, "\nERROR! Allocating private area failed\n");
445 return GL_FALSE;
446 }
447 /* parse information in __driConfigOptions */
448 driParseOptionInfo(&intelScreen->optionCache,
449 __driConfigOptions, __driNConfigOptions);
450
451 intelScreen->driScrnPriv = sPriv;
452 sPriv->private = (void *) intelScreen;
453 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
454 sarea = (struct drm_i915_sarea *)
455 (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
456
457 intelScreen->deviceID = gDRIPriv->deviceID;
458
459 intelUpdateScreenFromSAREA(intelScreen, sarea);
460
461 if (!intelMapScreenRegions(sPriv)) {
462 fprintf(stderr, "\nERROR! mapping regions\n");
463 _mesa_free(intelScreen);
464 sPriv->private = NULL;
465 return GL_FALSE;
466 }
467
468 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
469
470 if (0)
471 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
472
473 intelScreen->drmMinor = sPriv->drm_version.minor;
474
475 /* Determine if IRQs are active? */
476 if (!intel_get_param(sPriv, I915_PARAM_IRQ_ACTIVE,
477 &intelScreen->irq_active))
478 return GL_FALSE;
479
480 /* Determine if batchbuffers are allowed */
481 if (!intel_get_param(sPriv, I915_PARAM_ALLOW_BATCHBUFFER,
482 &intelScreen->allow_batchbuffer))
483 return GL_FALSE;
484
485 sPriv->extensions = intelExtensions;
486
487 return GL_TRUE;
488 }
489
490
491 static void
492 intelDestroyScreen(__DRIscreenPrivate * sPriv)
493 {
494 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
495
496 intelUnmapScreenRegions(intelScreen);
497
498 FREE(intelScreen);
499 sPriv->private = NULL;
500 }
501
502
503 /**
504 * This is called when we need to set up GL rendering to a new X window.
505 */
506 static GLboolean
507 intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
508 __DRIdrawablePrivate * driDrawPriv,
509 const __GLcontextModes * mesaVis, GLboolean isPixmap)
510 {
511 intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
512
513 if (isPixmap) {
514 return GL_FALSE; /* not implemented */
515 }
516 else {
517 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
518 mesaVis->depthBits != 24);
519 GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
520
521 struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer);
522
523 if (!intel_fb)
524 return GL_FALSE;
525
526 _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
527
528 /* setup the hardware-based renderbuffers */
529 {
530 intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat);
531 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
532 &intel_fb->color_rb[0]->Base);
533 }
534
535 if (mesaVis->doubleBufferMode) {
536 intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat);
537 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
538 &intel_fb->color_rb[1]->Base);
539
540 if (screen->third.handle) {
541 struct gl_renderbuffer *tmp_rb = NULL;
542
543 intel_fb->color_rb[2] = intel_create_renderbuffer(rgbFormat);
544 _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
545 }
546 }
547
548 if (mesaVis->depthBits == 24) {
549 if (mesaVis->stencilBits == 8) {
550 /* combined depth/stencil buffer */
551 struct intel_renderbuffer *depthStencilRb
552 = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT);
553 /* note: bind RB to two attachment points */
554 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
555 &depthStencilRb->Base);
556 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL,
557 &depthStencilRb->Base);
558 } else {
559 struct intel_renderbuffer *depthRb
560 = intel_create_renderbuffer(GL_DEPTH_COMPONENT24);
561 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
562 &depthRb->Base);
563 }
564 }
565 else if (mesaVis->depthBits == 16) {
566 /* just 16-bit depth buffer, no hw stencil */
567 struct intel_renderbuffer *depthRb
568 = intel_create_renderbuffer(GL_DEPTH_COMPONENT16);
569 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
570 }
571
572 /* now add any/all software-based renderbuffers we may need */
573 _mesa_add_soft_renderbuffers(&intel_fb->Base,
574 GL_FALSE, /* never sw color */
575 GL_FALSE, /* never sw depth */
576 swStencil, mesaVis->accumRedBits > 0,
577 GL_FALSE, /* never sw alpha */
578 GL_FALSE /* never sw aux */ );
579 driDrawPriv->driverPrivate = (void *) intel_fb;
580
581 return GL_TRUE;
582 }
583 }
584
585 static void
586 intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
587 {
588 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
589 }
590
591
592 /**
593 * Get information about previous buffer swaps.
594 */
595 static int
596 intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
597 {
598 struct intel_framebuffer *intel_fb;
599
600 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
601 || (sInfo == NULL)) {
602 return -1;
603 }
604
605 intel_fb = dPriv->driverPrivate;
606 sInfo->swap_count = intel_fb->swap_count;
607 sInfo->swap_ust = intel_fb->swap_ust;
608 sInfo->swap_missed_count = intel_fb->swap_missed_count;
609
610 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
611 ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust)
612 : 0.0;
613
614 return 0;
615 }
616
617
618 /* There are probably better ways to do this, such as an
619 * init-designated function to register chipids and createcontext
620 * functions.
621 */
622 extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
623 __DRIcontextPrivate * driContextPriv,
624 void *sharedContextPrivate);
625
626 extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
627 __DRIcontextPrivate * driContextPriv,
628 void *sharedContextPrivate);
629 extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis,
630 __DRIcontextPrivate * driContextPriv,
631 void *sharedContextPrivate);
632
633 static GLboolean
634 intelCreateContext(const __GLcontextModes * mesaVis,
635 __DRIcontextPrivate * driContextPriv,
636 void *sharedContextPrivate)
637 {
638 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
639 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
640
641 #ifdef I915
642 if (IS_9XX(intelScreen->deviceID)) {
643 if (!IS_965(intelScreen->deviceID)) {
644 return i915CreateContext(mesaVis, driContextPriv,
645 sharedContextPrivate);
646 }
647 } else {
648 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
649 }
650 #else
651 if (IS_965(intelScreen->deviceID))
652 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate);
653 #endif
654 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
655 return GL_FALSE;
656 }
657
658
659 static const struct __DriverAPIRec intelAPI = {
660 .DestroyScreen = intelDestroyScreen,
661 .CreateContext = intelCreateContext,
662 .DestroyContext = intelDestroyContext,
663 .CreateBuffer = intelCreateBuffer,
664 .DestroyBuffer = intelDestroyBuffer,
665 .SwapBuffers = intelSwapBuffers,
666 .MakeCurrent = intelMakeCurrent,
667 .UnbindContext = intelUnbindContext,
668 .GetSwapInfo = intelGetSwapInfo,
669 .GetDrawableMSC = driDrawableGetMSC32,
670 .WaitForMSC = driWaitForMSC32,
671 .WaitForSBC = NULL,
672 .SwapBuffersMSC = NULL,
673 .CopySubBuffer = intelCopySubBuffer,
674 .UpdateBuffer = intelUpdateBuffer,
675 };
676
677
678 static __GLcontextModes *
679 intelFillInModes(__DRIscreenPrivate *psp,
680 unsigned pixel_bits, unsigned depth_bits,
681 unsigned stencil_bits, GLboolean have_back_buffer)
682 {
683 __GLcontextModes *modes;
684 __GLcontextModes *m;
685 unsigned num_modes;
686 unsigned depth_buffer_factor;
687 unsigned back_buffer_factor;
688 GLenum fb_format;
689 GLenum fb_type;
690
691 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
692 * support pageflipping at all.
693 */
694 static const GLenum back_buffer_modes[] = {
695 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
696 };
697
698 u_int8_t depth_bits_array[3];
699 u_int8_t stencil_bits_array[3];
700
701
702 depth_bits_array[0] = 0;
703 depth_bits_array[1] = depth_bits;
704 depth_bits_array[2] = depth_bits;
705
706 /* Just like with the accumulation buffer, always provide some modes
707 * with a stencil buffer. It will be a sw fallback, but some apps won't
708 * care about that.
709 */
710 stencil_bits_array[0] = 0;
711 stencil_bits_array[1] = 0;
712 if (depth_bits == 24)
713 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
714
715 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
716
717 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
718 back_buffer_factor = (have_back_buffer) ? 3 : 1;
719
720 num_modes = depth_buffer_factor * back_buffer_factor * 4;
721
722 if (pixel_bits == 16) {
723 fb_format = GL_RGB;
724 fb_type = GL_UNSIGNED_SHORT_5_6_5;
725 }
726 else {
727 fb_format = GL_BGRA;
728 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
729 }
730
731 modes =
732 (*psp->contextModes->createContextModes) (num_modes,
733 sizeof(__GLcontextModes));
734 m = modes;
735 if (!driFillInModes(&m, fb_format, fb_type,
736 depth_bits_array, stencil_bits_array,
737 depth_buffer_factor, back_buffer_modes,
738 back_buffer_factor, GLX_TRUE_COLOR)) {
739 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
740 __LINE__);
741 return NULL;
742 }
743 if (!driFillInModes(&m, fb_format, fb_type,
744 depth_bits_array, stencil_bits_array,
745 depth_buffer_factor, back_buffer_modes,
746 back_buffer_factor, GLX_DIRECT_COLOR)) {
747 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
748 __LINE__);
749 return NULL;
750 }
751
752 /* Mark the visual as slow if there are "fake" stencil bits.
753 */
754 for (m = modes; m != NULL; m = m->next) {
755 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
756 m->visualRating = GLX_SLOW_CONFIG;
757 }
758 }
759
760 return modes;
761 }
762
763
764 /**
765 * This is the driver specific part of the createNewScreen entry point.
766 *
767 * \todo maybe fold this into intelInitDriver
768 *
769 * \return the __GLcontextModes supported by this driver
770 */
771 PUBLIC __GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp)
772 {
773 #ifdef I915
774 static const __DRIversion ddx_expected = { 1, 5, 0 };
775 #else
776 static const __DRIversion ddx_expected = { 1, 6, 0 };
777 #endif
778 static const __DRIversion dri_expected = { 4, 0, 0 };
779 static const __DRIversion drm_expected = { 1, 5, 0 };
780 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
781
782 psp->DriverAPI = intelAPI;
783
784 if (!driCheckDriDdxDrmVersions2("i915",
785 &psp->dri_version, &dri_expected,
786 &psp->ddx_version, &ddx_expected,
787 &psp->drm_version, &drm_expected)) {
788 return NULL;
789 }
790
791 /* Calling driInitExtensions here, with a NULL context pointer,
792 * does not actually enable the extensions. It just makes sure
793 * that all the dispatch offsets for all the extensions that
794 * *might* be enables are known. This is needed because the
795 * dispatch offsets need to be known when _mesa_context_create is
796 * called, but we can't enable the extensions until we have a
797 * context pointer.
798 *
799 * Hello chicken. Hello egg. How are you two today?
800 */
801 intelInitExtensions(NULL, GL_TRUE);
802
803 if (!intelInitDriver(psp))
804 return NULL;
805
806 return intelFillInModes(psp, dri_priv->cpp * 8,
807 (dri_priv->cpp == 2) ? 16 : 24,
808 (dri_priv->cpp == 2) ? 0 : 8, 1);
809 }
810
811 struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
812 {
813 /*
814 * This should probably change to have the screen allocate a dummy
815 * context at screen creation. For now just use the current context.
816 */
817
818 GET_CURRENT_CONTEXT(ctx);
819 if (ctx == NULL) {
820 _mesa_problem(NULL, "No current context in intelScreenContext\n");
821 return NULL;
822 }
823 return intel_context(ctx);
824 }
825
826 /**
827 * This is the driver specific part of the createNewScreen entry point.
828 *
829 * \return the __GLcontextModes supported by this driver
830 */
831 PUBLIC __GLcontextModes *__dri2DriverInitScreen(__DRIscreenPrivate *psp)
832 {
833 intelScreenPrivate *intelScreen;
834 __GLcontextModes *modes, *m;
835
836 psp->DriverAPI = intelAPI;
837
838 /* Calling driInitExtensions here, with a NULL context pointer,
839 * does not actually enable the extensions. It just makes sure
840 * that all the dispatch offsets for all the extensions that
841 * *might* be enables are known. This is needed because the
842 * dispatch offsets need to be known when _mesa_context_create is
843 * called, but we can't enable the extensions until we have a
844 * context pointer.
845 *
846 * Hello chicken. Hello egg. How are you two today?
847 */
848 intelInitExtensions(NULL, GL_TRUE);
849
850 /* Allocate the private area */
851 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
852 if (!intelScreen) {
853 fprintf(stderr, "\nERROR! Allocating private area failed\n");
854 return GL_FALSE;
855 }
856 /* parse information in __driConfigOptions */
857 driParseOptionInfo(&intelScreen->optionCache,
858 __driConfigOptions, __driNConfigOptions);
859
860 intelScreen->driScrnPriv = psp;
861 psp->private = (void *) intelScreen;
862
863 intelScreen->drmMinor = psp->drm_version.minor;
864
865 /* Determine chipset ID? */
866 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID,
867 &intelScreen->deviceID))
868 return GL_FALSE;
869
870 /* Determine if IRQs are active? */
871 if (!intel_get_param(psp, I915_PARAM_IRQ_ACTIVE,
872 &intelScreen->irq_active))
873 return GL_FALSE;
874
875 /* Determine if batchbuffers are allowed */
876 if (!intel_get_param(psp, I915_PARAM_ALLOW_BATCHBUFFER,
877 &intelScreen->allow_batchbuffer))
878 return GL_FALSE;
879
880 if (!intelScreen->allow_batchbuffer) {
881 fprintf(stderr, "batch buffer not allowed\n");
882 return GL_FALSE;
883 }
884
885 psp->extensions = intelExtensions;
886
887 modes = intelFillInModes(psp, 16, 16, 0, 1);
888 for (m = modes; m->next != NULL; m = m->next)
889 ;
890 m->next = intelFillInModes(psp, 32, 24, 8, 1);
891
892 return modes;
893 }