1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 #include "framebuffer.h"
32 #include "renderbuffer.h"
33 #include "simple_list.h"
39 #include "intel_screen.h"
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"
50 #include "intel_regions.h"
51 #include "intel_batchbuffer.h"
53 PUBLIC const char __driConfigOptions[] =
55 DRI_CONF_SECTION_PERFORMANCE
56 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
57 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
59 DRI_CONF_SECTION_QUALITY
60 DRI_CONF_FORCE_S3TC_ENABLE(false)
61 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
63 DRI_CONF_SECTION_DEBUG
64 DRI_CONF_NO_RAST(false)
68 const GLuint __driNConfigOptions = 5;
70 #ifdef USE_NEW_INTERFACE
71 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
72 #endif /*USE_NEW_INTERFACE */
74 extern const struct dri_extension card_extensions[];
75 extern const struct dri_extension ttm_extensions[];
78 * Map all the memory regions described by the screen.
79 * \return GL_TRUE if success, GL_FALSE if error.
82 intelMapScreenRegions(__DRIscreenPrivate * sPriv)
84 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
86 if (intelScreen->front.handle) {
88 intelScreen->front.handle,
89 intelScreen->front.size,
90 (drmAddress *) & intelScreen->front.map) != 0) {
91 _mesa_problem(NULL, "drmMap(frontbuffer) failed!");
96 _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
100 _mesa_printf("Back 0x%08x ", intelScreen->back.handle);
101 if (drmMap(sPriv->fd,
102 intelScreen->back.handle,
103 intelScreen->back.size,
104 (drmAddress *) & intelScreen->back.map) != 0) {
105 intelUnmapScreenRegions(intelScreen);
109 if (intelScreen->third.handle) {
111 _mesa_printf("Third 0x%08x ", intelScreen->third.handle);
112 if (drmMap(sPriv->fd,
113 intelScreen->third.handle,
114 intelScreen->third.size,
115 (drmAddress *) & intelScreen->third.map) != 0) {
116 intelUnmapScreenRegions(intelScreen);
122 _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);
123 if (drmMap(sPriv->fd,
124 intelScreen->depth.handle,
125 intelScreen->depth.size,
126 (drmAddress *) & intelScreen->depth.map) != 0) {
127 intelUnmapScreenRegions(intelScreen);
132 _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
133 if (intelScreen->tex.size != 0) {
134 if (drmMap(sPriv->fd,
135 intelScreen->tex.handle,
136 intelScreen->tex.size,
137 (drmAddress *) & intelScreen->tex.map) != 0) {
138 intelUnmapScreenRegions(intelScreen);
144 printf("Mappings: front: %p back: %p third: %p depth: %p tex: %p\n",
145 intelScreen->front.map,
146 intelScreen->back.map, intelScreen->third.map,
147 intelScreen->depth.map, intelScreen->tex.map);
152 intelUnmapScreenRegions(intelScreenPrivate * intelScreen)
154 #define REALLY_UNMAP 1
155 if (intelScreen->front.map) {
157 if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0)
158 printf("drmUnmap front failed!\n");
160 intelScreen->front.map = NULL;
162 if (intelScreen->back.map) {
164 if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0)
165 printf("drmUnmap back failed!\n");
167 intelScreen->back.map = NULL;
169 if (intelScreen->third.map) {
171 if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0)
172 printf("drmUnmap third failed!\n");
174 intelScreen->third.map = NULL;
176 if (intelScreen->depth.map) {
178 drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
179 intelScreen->depth.map = NULL;
182 if (intelScreen->tex.map) {
184 drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
185 intelScreen->tex.map = NULL;
192 intelPrintDRIInfo(intelScreenPrivate * intelScreen,
193 __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
195 fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
196 intelScreen->front.size, intelScreen->front.offset,
198 fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n",
199 intelScreen->back.size, intelScreen->back.offset,
201 fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n",
202 intelScreen->depth.size, intelScreen->depth.offset,
204 fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n",
205 intelScreen->tex.size, intelScreen->tex.offset);
206 fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
211 intelPrintSAREA(const drmI830Sarea * sarea)
213 fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width,
215 fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
217 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
218 sarea->front_offset, sarea->front_size,
219 (unsigned) sarea->front_handle);
221 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
222 sarea->back_offset, sarea->back_size,
223 (unsigned) sarea->back_handle);
224 fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
225 sarea->depth_offset, sarea->depth_size,
226 (unsigned) sarea->depth_handle);
227 fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
228 sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
233 * A number of the screen parameters are obtained/computed from
234 * information in the SAREA. This function updates those parameters.
237 intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
238 drmI830Sarea * sarea)
240 intelScreen->width = sarea->width;
241 intelScreen->height = sarea->height;
242 intelScreen->pitch = sarea->pitch;
244 intelScreen->front.offset = sarea->front_offset;
245 intelScreen->front.handle = sarea->front_handle;
246 intelScreen->front.size = sarea->front_size;
247 intelScreen->front.tiled = sarea->front_tiled;
249 intelScreen->back.offset = sarea->back_offset;
250 intelScreen->back.handle = sarea->back_handle;
251 intelScreen->back.size = sarea->back_size;
252 intelScreen->back.tiled = sarea->back_tiled;
254 if (intelScreen->driScrnPriv->ddx_version.minor >= 8) {
255 intelScreen->third.offset = sarea->third_offset;
256 intelScreen->third.handle = sarea->third_handle;
257 intelScreen->third.size = sarea->third_size;
258 intelScreen->third.tiled = sarea->third_tiled;
261 intelScreen->depth.offset = sarea->depth_offset;
262 intelScreen->depth.handle = sarea->depth_handle;
263 intelScreen->depth.size = sarea->depth_size;
264 intelScreen->depth.tiled = sarea->depth_tiled;
266 if (intelScreen->driScrnPriv->ddx_version.minor >= 9) {
267 intelScreen->front.bo_handle = sarea->front_bo_handle;
268 intelScreen->back.bo_handle = sarea->back_bo_handle;
269 intelScreen->third.bo_handle = sarea->third_bo_handle;
270 intelScreen->depth.bo_handle = sarea->depth_bo_handle;
272 intelScreen->front.bo_handle = -1;
273 intelScreen->back.bo_handle = -1;
274 intelScreen->third.bo_handle = -1;
275 intelScreen->depth.bo_handle = -1;
278 intelScreen->tex.offset = sarea->tex_offset;
279 intelScreen->logTextureGranularity = sarea->log_tex_granularity;
280 intelScreen->tex.handle = sarea->tex_handle;
281 intelScreen->tex.size = sarea->tex_size;
284 intelPrintSAREA(sarea);
287 static const __DRItexOffsetExtension intelTexOffsetExtension = {
288 { __DRI_TEX_OFFSET },
292 static const __DRIextension *intelExtensions[] = {
293 &driReadDrawableExtension,
294 &driCopySubBufferExtension.base,
295 &driSwapControlExtension.base,
296 &driFrameTrackingExtension.base,
297 &driMediaStreamCounterExtension.base,
298 &intelTexOffsetExtension.base,
303 intel_get_param(__DRIscreenPrivate *psp, int param, int *value)
311 ret = drmCommandWriteRead(psp->fd, DRM_I830_GETPARAM, &gp, sizeof(gp));
313 fprintf(stderr, "drmI830GetParam: %d\n", ret);
320 static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
322 intelScreenPrivate *intelScreen;
323 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
326 if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
328 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
332 /* Allocate the private area */
333 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
335 fprintf(stderr, "\nERROR! Allocating private area failed\n");
338 /* parse information in __driConfigOptions */
339 driParseOptionInfo(&intelScreen->optionCache,
340 __driConfigOptions, __driNConfigOptions);
342 intelScreen->driScrnPriv = sPriv;
343 sPriv->private = (void *) intelScreen;
344 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
345 sarea = (drmI830Sarea *)
346 (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
348 intelScreen->deviceID = gDRIPriv->deviceID;
350 intelUpdateScreenFromSAREA(intelScreen, sarea);
352 if (!intelMapScreenRegions(sPriv)) {
353 fprintf(stderr, "\nERROR! mapping regions\n");
354 _mesa_free(intelScreen);
355 sPriv->private = NULL;
359 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
362 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
364 intelScreen->drmMinor = sPriv->drm_version.minor;
366 /* Determine if IRQs are active? */
367 if (!intel_get_param(sPriv, I830_PARAM_IRQ_ACTIVE,
368 &intelScreen->irq_active))
371 /* Determine if batchbuffers are allowed */
372 if (!intel_get_param(sPriv, I830_PARAM_ALLOW_BATCHBUFFER,
373 &intelScreen->allow_batchbuffer))
376 sPriv->extensions = intelExtensions;
383 intelDestroyScreen(__DRIscreenPrivate * sPriv)
385 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
387 intelUnmapScreenRegions(intelScreen);
390 sPriv->private = NULL;
395 * This is called when we need to set up GL rendering to a new X window.
398 intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
399 __DRIdrawablePrivate * driDrawPriv,
400 const __GLcontextModes * mesaVis, GLboolean isPixmap)
402 intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
405 return GL_FALSE; /* not implemented */
408 GLboolean swStencil = (mesaVis->stencilBits > 0 &&
409 mesaVis->depthBits != 24);
410 GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
412 struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer);
417 _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
419 /* setup the hardware-based renderbuffers */
421 intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat);
422 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
423 &intel_fb->color_rb[0]->Base);
426 if (mesaVis->doubleBufferMode) {
427 intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat);
428 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
429 &intel_fb->color_rb[1]->Base);
431 if (screen->third.handle) {
432 struct gl_renderbuffer *tmp_rb = NULL;
434 intel_fb->color_rb[2] = intel_create_renderbuffer(rgbFormat);
435 _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
439 if (mesaVis->depthBits == 24) {
440 if (mesaVis->stencilBits == 8) {
441 /* combined depth/stencil buffer */
442 struct intel_renderbuffer *depthStencilRb
443 = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT);
444 /* note: bind RB to two attachment points */
445 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
446 &depthStencilRb->Base);
447 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL,
448 &depthStencilRb->Base);
450 struct intel_renderbuffer *depthRb
451 = intel_create_renderbuffer(GL_DEPTH_COMPONENT24);
452 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
456 else if (mesaVis->depthBits == 16) {
457 /* just 16-bit depth buffer, no hw stencil */
458 struct intel_renderbuffer *depthRb
459 = intel_create_renderbuffer(GL_DEPTH_COMPONENT16);
460 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
463 /* now add any/all software-based renderbuffers we may need */
464 _mesa_add_soft_renderbuffers(&intel_fb->Base,
465 GL_FALSE, /* never sw color */
466 GL_FALSE, /* never sw depth */
467 swStencil, mesaVis->accumRedBits > 0,
468 GL_FALSE, /* never sw alpha */
469 GL_FALSE /* never sw aux */ );
470 driDrawPriv->driverPrivate = (void *) intel_fb;
477 intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
479 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
484 * Get information about previous buffer swaps.
487 intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
489 struct intel_framebuffer *intel_fb;
491 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
492 || (sInfo == NULL)) {
496 intel_fb = dPriv->driverPrivate;
497 sInfo->swap_count = intel_fb->swap_count;
498 sInfo->swap_ust = intel_fb->swap_ust;
499 sInfo->swap_missed_count = intel_fb->swap_missed_count;
501 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
502 ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust)
509 /* There are probably better ways to do this, such as an
510 * init-designated function to register chipids and createcontext
513 extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
514 __DRIcontextPrivate * driContextPriv,
515 void *sharedContextPrivate);
517 extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
518 __DRIcontextPrivate * driContextPriv,
519 void *sharedContextPrivate);
520 extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis,
521 __DRIcontextPrivate * driContextPriv,
522 void *sharedContextPrivate);
525 intelCreateContext(const __GLcontextModes * mesaVis,
526 __DRIcontextPrivate * driContextPriv,
527 void *sharedContextPrivate)
529 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
530 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
533 if (IS_9XX(intelScreen->deviceID)) {
534 if (!IS_965(intelScreen->deviceID)) {
535 return i915CreateContext(mesaVis, driContextPriv,
536 sharedContextPrivate);
539 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
542 if (IS_965(intelScreen->deviceID))
543 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate);
545 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
550 static const struct __DriverAPIRec intelAPI = {
551 .DestroyScreen = intelDestroyScreen,
552 .CreateContext = intelCreateContext,
553 .DestroyContext = intelDestroyContext,
554 .CreateBuffer = intelCreateBuffer,
555 .DestroyBuffer = intelDestroyBuffer,
556 .SwapBuffers = intelSwapBuffers,
557 .MakeCurrent = intelMakeCurrent,
558 .UnbindContext = intelUnbindContext,
559 .GetSwapInfo = intelGetSwapInfo,
560 .GetMSC = driGetMSC32,
561 .GetDrawableMSC = driDrawableGetMSC32,
562 .WaitForMSC = driWaitForMSC32,
564 .SwapBuffersMSC = NULL,
565 .CopySubBuffer = intelCopySubBuffer,
567 .setTexOffset = intelSetTexOffset,
572 static __GLcontextModes *
573 intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
574 unsigned stencil_bits, GLboolean have_back_buffer)
576 __GLcontextModes *modes;
579 unsigned depth_buffer_factor;
580 unsigned back_buffer_factor;
584 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
585 * support pageflipping at all.
587 static const GLenum back_buffer_modes[] = {
588 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
591 u_int8_t depth_bits_array[3];
592 u_int8_t stencil_bits_array[3];
595 depth_bits_array[0] = 0;
596 depth_bits_array[1] = depth_bits;
597 depth_bits_array[2] = depth_bits;
599 /* Just like with the accumulation buffer, always provide some modes
600 * with a stencil buffer. It will be a sw fallback, but some apps won't
603 stencil_bits_array[0] = 0;
604 stencil_bits_array[1] = 0;
605 if (depth_bits == 24)
606 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
608 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
610 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
611 back_buffer_factor = (have_back_buffer) ? 3 : 1;
613 num_modes = depth_buffer_factor * back_buffer_factor * 4;
615 if (pixel_bits == 16) {
617 fb_type = GL_UNSIGNED_SHORT_5_6_5;
621 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
625 (*dri_interface->createContextModes) (num_modes,
626 sizeof(__GLcontextModes));
628 if (!driFillInModes(&m, fb_format, fb_type,
629 depth_bits_array, stencil_bits_array,
630 depth_buffer_factor, back_buffer_modes,
631 back_buffer_factor, GLX_TRUE_COLOR)) {
632 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
636 if (!driFillInModes(&m, fb_format, fb_type,
637 depth_bits_array, stencil_bits_array,
638 depth_buffer_factor, back_buffer_modes,
639 back_buffer_factor, GLX_DIRECT_COLOR)) {
640 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
645 /* Mark the visual as slow if there are "fake" stencil bits.
647 for (m = modes; m != NULL; m = m->next) {
648 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
649 m->visualRating = GLX_SLOW_CONFIG;
658 * This is the driver specific part of the createNewScreen entry point.
660 * \todo maybe fold this into intelInitDriver
662 * \return the __GLcontextModes supported by this driver
664 PUBLIC __GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp)
667 static const __DRIversion ddx_expected = { 1, 5, 0 };
669 static const __DRIversion ddx_expected = { 1, 6, 0 };
671 static const __DRIversion dri_expected = { 4, 0, 0 };
672 static const __DRIversion drm_expected = { 1, 5, 0 };
673 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
675 psp->DriverAPI = intelAPI;
677 if (!driCheckDriDdxDrmVersions2("i915",
678 &psp->dri_version, &dri_expected,
679 &psp->ddx_version, &ddx_expected,
680 &psp->drm_version, &drm_expected)) {
684 /* Calling driInitExtensions here, with a NULL context pointer,
685 * does not actually enable the extensions. It just makes sure
686 * that all the dispatch offsets for all the extensions that
687 * *might* be enables are known. This is needed because the
688 * dispatch offsets need to be known when _mesa_context_create is
689 * called, but we can't enable the extensions until we have a
692 * Hello chicken. Hello egg. How are you two today?
694 driInitExtensions(NULL, card_extensions, GL_FALSE);
695 driInitExtensions(NULL, ttm_extensions, GL_FALSE);
697 if (!intelInitDriver(psp))
700 return intelFillInModes(dri_priv->cpp * 8,
701 (dri_priv->cpp == 2) ? 16 : 24,
702 (dri_priv->cpp == 2) ? 0 : 8, 1);
705 struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
708 * This should probably change to have the screen allocate a dummy
709 * context at screen creation. For now just use the current context.
712 GET_CURRENT_CONTEXT(ctx);
714 _mesa_problem(NULL, "No current context in intelScreenContext\n");
717 return intel_context(ctx);