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 **************************************************************************/
32 #include "intel_context.h"
33 #include "intel_screen.h"
34 #include "intel_batchbuffer.h"
35 #include "intel_swapbuffers.h"
38 #include "ws_dri_bufpool.h"
40 #include "pipe/p_context.h"
41 #include "pipe/p_screen.h"
42 #include "pipe/p_inlines.h"
43 #include "state_tracker/st_public.h"
44 #include "state_tracker/st_cb_fbo.h"
47 intelCreateSurface(struct intel_screen
*intelScreen
, struct pipe_winsys
*winsys
, unsigned handle
);
50 intelCreateSurface(struct intel_screen
*intelScreen
, struct pipe_winsys
*winsys
, unsigned handle
)
52 struct pipe_screen
*screen
= intelScreen
->base
.screen
;
53 struct pipe_texture
*texture
;
54 struct pipe_texture templat
;
55 struct pipe_surface
*surface
;
56 struct pipe_buffer
*buffer
;
59 assert(intelScreen
->front
.cpp
== 4);
61 buffer
= intel_be_buffer_from_handle(&intelScreen
->base
,
67 intelScreen
->front
.buffer
= dri_bo(buffer
);
69 memset(&templat
, 0, sizeof(templat
));
70 templat
.tex_usage
|= PIPE_TEXTURE_USAGE_DISPLAY_TARGET
;
71 templat
.target
= PIPE_TEXTURE_2D
;
72 templat
.last_level
= 0;
74 templat
.format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
75 templat
.width
[0] = intelScreen
->front
.width
;
76 templat
.height
[0] = intelScreen
->front
.height
;
77 pf_get_block(templat
.format
, &templat
.block
);
78 pitch
= intelScreen
->front
.pitch
;
80 texture
= screen
->texture_blanket(screen
,
85 /* Unref the buffer we don't need it anyways */
86 pipe_buffer_reference(screen
, &buffer
, NULL
);
88 surface
= screen
->get_tex_surface(screen
,
93 PIPE_BUFFER_USAGE_GPU_WRITE
);
95 intelScreen
->front
.texture
= texture
;
96 intelScreen
->front
.surface
= surface
;
99 PUBLIC
const char __driConfigOptions
[] =
100 DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
101 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS
)
102 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
103 DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
104 // DRI_CONF_FORCE_S3TC_ENABLE(false)
105 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
106 DRI_CONF_SECTION_END DRI_CONF_END
;
108 const uint __driNConfigOptions
= 3;
110 #ifdef USE_NEW_INTERFACE
111 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
112 #endif /*USE_NEW_INTERFACE */
114 extern const struct dri_extension card_extensions
[];
117 intel_get_param(__DRIscreenPrivate
*psp
, int param
, int *value
)
120 struct drm_i915_getparam gp
;
125 ret
= drmCommandWriteRead(psp
->fd
, DRM_I915_GETPARAM
, &gp
, sizeof(gp
));
127 fprintf(stderr
, "drm_i915_getparam: %d\n", ret
);
135 intelSetTexOffset(__DRIcontext
*pDRICtx
, int texname
,
136 unsigned long long offset
, int depth
, uint pitch
)
140 struct intel_context
*intel
= (struct intel_context
*)
141 ((__DRIcontextPrivate
*)pDRICtx
->private)->driverPrivate
;
142 struct gl_texture_object
*tObj
= _mesa_lookup_texture(&intel
->ctx
, texname
);
143 struct st_texture_object
*stObj
= st_texture_object(tObj
);
149 st
->pipe
->texture_release(intel
->st
->pipe
, &stObj
->pt
);
151 stObj
->imageOverride
= GL_TRUE
;
152 stObj
->depthOverride
= depth
;
153 stObj
->pitchOverride
= pitch
;
156 stObj
->textureOffset
= offset
;
163 intelHandleDrawableConfig(__DRIdrawablePrivate
*dPriv
,
164 __DRIcontextPrivate
*pcp
,
165 __DRIDrawableConfigEvent
*event
)
175 intelHandleBufferAttach(__DRIdrawablePrivate
*dPriv
,
176 __DRIcontextPrivate
*pcp
,
177 __DRIBufferAttachEvent
*ba
)
179 struct intel_screen
*intelScreen
= intel_screen(dPriv
->driScreenPriv
);
181 switch (ba
->buffer
.attachment
) {
182 case DRI_DRAWABLE_BUFFER_FRONT_LEFT
:
183 intelScreen
->front
.width
= dPriv
->w
;
184 intelScreen
->front
.height
= dPriv
->h
;
185 intelScreen
->front
.cpp
= ba
->buffer
.cpp
;
186 intelScreen
->front
.pitch
= ba
->buffer
.pitch
;
187 driGenBuffers(intelScreen
->base
.staticPool
, "front", 1, &intelScreen
->front
.buffer
, 0, 0, 0);
188 driBOSetReferenced(intelScreen
->front
.buffer
, ba
->buffer
.handle
);
191 case DRI_DRAWABLE_BUFFER_BACK_LEFT
:
192 case DRI_DRAWABLE_BUFFER_DEPTH
:
193 case DRI_DRAWABLE_BUFFER_STENCIL
:
194 case DRI_DRAWABLE_BUFFER_ACCUM
:
199 fprintf(stderr
, "unhandled buffer attach event, attachment type %d\n",
200 ba
->buffer
.attachment
);
206 static const __DRItexOffsetExtension intelTexOffsetExtension
= {
207 { __DRI_TEX_OFFSET
},
212 static const __DRItexBufferExtension intelTexBufferExtension
= {
213 { __DRI_TEX_BUFFER
, __DRI_TEX_BUFFER_VERSION
},
218 static const __DRIextension
*intelScreenExtensions
[] = {
219 &driReadDrawableExtension
,
220 &driCopySubBufferExtension
.base
,
221 &driSwapControlExtension
.base
,
222 &driFrameTrackingExtension
.base
,
223 &driMediaStreamCounterExtension
.base
,
224 &intelTexOffsetExtension
.base
,
225 // &intelTexBufferExtension.base,
231 intelPrintDRIInfo(struct intel_screen
* intelScreen
,
232 __DRIscreenPrivate
* sPriv
, I830DRIPtr gDRIPriv
)
234 fprintf(stderr
, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
235 intelScreen
->front
.size
, intelScreen
->front
.offset
,
236 intelScreen
->front
.pitch
);
237 fprintf(stderr
, "*** Memory : 0x%x\n", gDRIPriv
->mem
);
243 intelPrintSAREA(const drmI830Sarea
* sarea
)
245 fprintf(stderr
, "SAREA: sarea width %d height %d\n", sarea
->width
,
247 fprintf(stderr
, "SAREA: pitch: %d\n", sarea
->pitch
);
249 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
250 sarea
->front_offset
, sarea
->front_size
,
251 (unsigned) sarea
->front_handle
);
253 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
254 sarea
->back_offset
, sarea
->back_size
,
255 (unsigned) sarea
->back_handle
);
256 fprintf(stderr
, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
257 sarea
->depth_offset
, sarea
->depth_size
,
258 (unsigned) sarea
->depth_handle
);
259 fprintf(stderr
, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
260 sarea
->tex_offset
, sarea
->tex_size
, (unsigned) sarea
->tex_handle
);
261 fprintf(stderr
, "SAREA: rotation: %d\n", sarea
->rotation
);
263 "SAREA: rotated offset: 0x%08x size: 0x%x\n",
264 sarea
->rotated_offset
, sarea
->rotated_size
);
265 fprintf(stderr
, "SAREA: rotated pitch: %d\n", sarea
->rotated_pitch
);
271 * Use the information in the sarea to update the screen parameters
272 * related to screen rotation. Needs to be called locked.
275 intelUpdateScreenRotation(__DRIscreenPrivate
* sPriv
, drmI830Sarea
* sarea
)
277 struct intel_screen
*intelScreen
= intel_screen(sPriv
);
279 if (intelScreen
->front
.map
) {
280 drmUnmap(intelScreen
->front
.map
, intelScreen
->front
.size
);
281 intelScreen
->front
.map
= NULL
;
284 if (intelScreen
->front
.buffer
)
285 driDeleteBuffers(1, &intelScreen
->front
.buffer
);
287 intelScreen
->front
.width
= sarea
->width
;
288 intelScreen
->front
.height
= sarea
->height
;
289 intelScreen
->front
.offset
= sarea
->front_offset
;
290 intelScreen
->front
.pitch
= sarea
->pitch
* intelScreen
->front
.cpp
;
291 intelScreen
->front
.size
= sarea
->front_size
;
292 intelScreen
->front
.handle
= sarea
->front_handle
;
294 assert( sarea
->front_size
>=
295 intelScreen
->front
.pitch
* intelScreen
->front
.height
);
297 #if 0 /* JB not important */
298 if (!sarea
->front_handle
)
301 if (drmMap(sPriv
->fd
,
303 intelScreen
->front
.size
,
304 (drmAddress
*) & intelScreen
->front
.map
) != 0) {
305 fprintf(stderr
, "drmMap(frontbuffer) failed!\n");
311 if (intelScreen
->staticPool
) {
312 driGenBuffers(intelScreen
->staticPool
, "static region", 1,
313 &intelScreen
->front
.buffer
, 64,
314 DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_NO_MOVE
|
315 DRM_BO_FLAG_READ
| DRM_BO_FLAG_WRITE
, 0);
317 driBOSetStatic(intelScreen
->front
.buffer
,
318 intelScreen
->front
.offset
,
319 intelScreen
->front
.pitch
* intelScreen
->front
.height
,
320 intelScreen
->front
.map
, 0);
323 if (intelScreen
->base
.staticPool
) {
324 if (intelScreen
->front
.buffer
) {
325 driBOUnReference(intelScreen
->front
.buffer
);
326 pipe_surface_reference(&intelScreen
->front
.surface
, NULL
);
327 pipe_texture_reference(&intelScreen
->front
.texture
, NULL
);
329 intelCreateSurface(intelScreen
, &intelScreen
->base
.base
, sarea
->front_bo_handle
);
336 intelCreatePools(__DRIscreenPrivate
* sPriv
)
338 //unsigned batchPoolSize = 1024*1024;
339 struct intel_screen
*intelScreen
= intel_screen(sPriv
);
341 if (intelScreen
->havePools
)
344 intelScreen
->havePools
= GL_TRUE
;
346 if (intelScreen
->sarea
)
347 intelUpdateScreenRotation(sPriv
, intelScreen
->sarea
);
353 intel_get_name( struct pipe_winsys
*winsys
)
355 return "Intel/DRI/ttm";
359 * The state tracker (should!) keep track of whether the fake
360 * frontbuffer has been touched by any rendering since the last time
361 * we copied its contents to the real frontbuffer. Our task is easy:
364 intel_flush_frontbuffer( struct pipe_winsys
*winsys
,
365 struct pipe_surface
*surf
,
366 void *context_private
)
368 struct intel_context
*intel
= (struct intel_context
*) context_private
;
369 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
371 intelDisplaySurface(dPriv
, surf
, NULL
);
375 intelInitDriver(__DRIscreenPrivate
* sPriv
)
377 struct intel_screen
*intelScreen
;
378 I830DRIPtr gDRIPriv
= (I830DRIPtr
) sPriv
->pDevPriv
;
380 if (sPriv
->devPrivSize
!= sizeof(I830DRIRec
)) {
382 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
386 /* Allocate the private area */
387 intelScreen
= CALLOC_STRUCT(intel_screen
);
391 /* parse information in __driConfigOptions */
392 driParseOptionInfo(&intelScreen
->optionCache
,
393 __driConfigOptions
, __driNConfigOptions
);
395 sPriv
->private = (void *) intelScreen
;
396 intelScreen
->sarea
= (drmI830Sarea
*) (((GLubyte
*) sPriv
->pSAREA
) +
397 gDRIPriv
->sarea_priv_offset
);
399 intelScreen
->deviceID
= gDRIPriv
->deviceID
;
401 intelScreen
->front
.cpp
= gDRIPriv
->cpp
;
402 intelScreen
->drmMinor
= sPriv
->drm_version
.minor
;
403 intelUpdateScreenRotation(sPriv
, intelScreen
->sarea
);
406 intelPrintDRIInfo(intelScreen
, sPriv
, gDRIPriv
);
408 sPriv
->extensions
= intelScreenExtensions
;
410 intelScreen
->base
.base
.flush_frontbuffer
= intel_flush_frontbuffer
;
411 intelScreen
->base
.base
.get_name
= intel_get_name
;
412 intel_be_init_device(&intelScreen
->base
, sPriv
->fd
, intelScreen
->deviceID
);
419 intelDestroyScreen(__DRIscreenPrivate
* sPriv
)
421 struct intel_screen
*intelScreen
= intel_screen(sPriv
);
423 intel_be_destroy_device(&intelScreen
->base
);
424 /* intelUnmapScreenRegions(intelScreen); */
427 sPriv
->private = NULL
;
432 * This is called when we need to set up GL rendering to a new X window.
435 intelCreateBuffer(__DRIscreenPrivate
* driScrnPriv
,
436 __DRIdrawablePrivate
* driDrawPriv
,
437 const __GLcontextModes
* visual
, boolean isPixmap
)
440 return GL_FALSE
; /* not implemented */
443 enum pipe_format colorFormat
, depthFormat
, stencilFormat
;
444 struct intel_framebuffer
*intelfb
= CALLOC_STRUCT(intel_framebuffer
);
449 if (visual
->redBits
== 5)
450 colorFormat
= PIPE_FORMAT_R5G6B5_UNORM
;
452 colorFormat
= PIPE_FORMAT_A8R8G8B8_UNORM
;
454 if (visual
->depthBits
== 16)
455 depthFormat
= PIPE_FORMAT_Z16_UNORM
;
456 else if (visual
->depthBits
== 24)
457 depthFormat
= PIPE_FORMAT_S8Z24_UNORM
;
459 depthFormat
= PIPE_FORMAT_NONE
;
461 if (visual
->stencilBits
== 8)
462 stencilFormat
= PIPE_FORMAT_S8Z24_UNORM
;
464 stencilFormat
= PIPE_FORMAT_NONE
;
466 intelfb
->stfb
= st_create_framebuffer(visual
,
473 if (!intelfb
->stfb
) {
478 driDrawPriv
->driverPrivate
= (void *) intelfb
;
484 intelDestroyBuffer(__DRIdrawablePrivate
* driDrawPriv
)
486 struct intel_framebuffer
*intelfb
= intel_framebuffer(driDrawPriv
);
487 assert(intelfb
->stfb
);
488 st_unreference_framebuffer(intelfb
->stfb
);
494 * Get information about previous buffer swaps.
497 intelGetSwapInfo(__DRIdrawablePrivate
* dPriv
, __DRIswapInfo
* sInfo
)
499 if ((dPriv
== NULL
) || (dPriv
->driverPrivate
== NULL
)
500 || (sInfo
== NULL
)) {
507 static __DRIconfig
**
508 intelFillInModes(__DRIscreenPrivate
*psp
,
509 unsigned pixel_bits
, unsigned depth_bits
,
510 unsigned stencil_bits
, GLboolean have_back_buffer
)
512 __DRIconfig
**configs
;
515 unsigned depth_buffer_factor
;
516 unsigned back_buffer_factor
;
521 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
522 * support pageflipping at all.
524 static const GLenum back_buffer_modes
[] = {
525 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
528 uint8_t depth_bits_array
[3];
529 uint8_t stencil_bits_array
[3];
530 uint8_t msaa_samples_array
[1];
533 depth_bits_array
[0] = 0;
534 depth_bits_array
[1] = depth_bits
;
535 depth_bits_array
[2] = depth_bits
;
536 msaa_samples_array
[0] = 0;
538 /* Just like with the accumulation buffer, always provide some modes
539 * with a stencil buffer. It will be a sw fallback, but some apps won't
542 stencil_bits_array
[0] = 0;
543 stencil_bits_array
[1] = 0;
544 if (depth_bits
== 24)
545 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
547 stencil_bits_array
[2] = (stencil_bits
== 0) ? 8 : stencil_bits
;
549 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 3 : 1;
550 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
552 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
554 if (pixel_bits
== 16) {
556 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
560 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
563 configs
= driCreateConfigs(fb_format
, fb_type
,
564 depth_bits_array
, stencil_bits_array
,
565 depth_buffer_factor
, back_buffer_modes
,
566 back_buffer_factor
, msaa_samples_array
, 1);
567 if (configs
== NULL
) {
568 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
573 /* Mark the visual as slow if there are "fake" stencil bits.
575 for (i
= 0; configs
[i
]; i
++) {
576 m
= &configs
[i
]->modes
;
577 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
578 m
->visualRating
= GLX_SLOW_CONFIG
;
586 * This is the driver specific part of the createNewScreen entry point.
588 * \todo maybe fold this into intelInitDriver
590 * \return the __GLcontextModes supported by this driver
592 static const __DRIconfig
**intelInitScreen(__DRIscreenPrivate
*psp
)
595 static const __DRIversion ddx_expected
= { 1, 5, 0 };
597 static const __DRIversion ddx_expected
= { 1, 6, 0 };
599 static const __DRIversion dri_expected
= { 4, 0, 0 };
600 static const __DRIversion drm_expected
= { 1, 5, 0 };
601 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
603 if (!driCheckDriDdxDrmVersions2("i915",
604 &psp
->dri_version
, &dri_expected
,
605 &psp
->ddx_version
, &ddx_expected
,
606 &psp
->drm_version
, &drm_expected
)) {
610 /* Calling driInitExtensions here, with a NULL context pointer,
611 * does not actually enable the extensions. It just makes sure
612 * that all the dispatch offsets for all the extensions that
613 * *might* be enables are known. This is needed because the
614 * dispatch offsets need to be known when _mesa_context_create is
615 * called, but we can't enable the extensions until we have a
618 * Hello chicken. Hello egg. How are you two today?
620 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
621 //intelInitExtensions(NULL, GL_TRUE);
623 if (!intelInitDriver(psp
))
626 psp
->extensions
= intelScreenExtensions
;
628 return (const __DRIconfig
**)
629 intelFillInModes(psp
, dri_priv
->cpp
* 8,
630 (dri_priv
->cpp
== 2) ? 16 : 24,
631 (dri_priv
->cpp
== 2) ? 0 : 8, 1);
635 * This is the driver specific part of the createNewScreen entry point.
637 * \return the __GLcontextModes supported by this driver
640 __DRIconfig
**intelInitScreen2(__DRIscreenPrivate
*psp
)
642 struct intel_screen
*intelScreen
;
644 /* Calling driInitExtensions here, with a NULL context pointer,
645 * does not actually enable the extensions. It just makes sure
646 * that all the dispatch offsets for all the extensions that
647 * *might* be enables are known. This is needed because the
648 * dispatch offsets need to be known when _mesa_context_create is
649 * called, but we can't enable the extensions until we have a
652 * Hello chicken. Hello egg. How are you two today?
654 //intelInitExtensions(NULL, GL_TRUE);
656 /* Allocate the private area */
657 intelScreen
= CALLOC_STRUCT(intel_screen
);
659 fprintf(stderr
, "\nERROR! Allocating private area failed\n");
662 /* parse information in __driConfigOptions */
663 driParseOptionInfo(&intelScreen
->optionCache
,
664 __driConfigOptions
, __driNConfigOptions
);
666 psp
->private = (void *) intelScreen
;
668 intelScreen
->drmMinor
= psp
->drm_version
.minor
;
670 /* Determine chipset ID? */
671 if (!intel_get_param(psp
, I915_PARAM_CHIPSET_ID
,
672 &intelScreen
->deviceID
))
675 psp
->extensions
= intelScreenExtensions
;
677 intel_be_init_device(&intelScreen
->base
, psp
->fd
, intelScreen
->deviceID
);
678 intelScreen
->base
.base
.flush_frontbuffer
= intel_flush_frontbuffer
;
679 intelScreen
->base
.base
.get_name
= intel_get_name
;
681 return driConcatConfigs(intelFillInModes(psp
, 16, 16, 0, 1),
682 intelFillInModes(psp
, 32, 24, 8, 1));
685 const struct __DriverAPIRec driDriverAPI
= {
686 .InitScreen
= intelInitScreen
,
687 .DestroyScreen
= intelDestroyScreen
,
688 .CreateContext
= intelCreateContext
,
689 .DestroyContext
= intelDestroyContext
,
690 .CreateBuffer
= intelCreateBuffer
,
691 .DestroyBuffer
= intelDestroyBuffer
,
692 .SwapBuffers
= intelSwapBuffers
,
693 .MakeCurrent
= intelMakeCurrent
,
694 .UnbindContext
= intelUnbindContext
,
695 .GetSwapInfo
= intelGetSwapInfo
,
696 .GetDrawableMSC
= driDrawableGetMSC32
,
697 .WaitForMSC
= driWaitForMSC32
,
698 .CopySubBuffer
= intelCopySubBuffer
,
700 //.InitScreen2 = intelInitScreen2,
701 //.HandleDrawableConfig = intelHandleDrawableConfig,
702 //.HandleBufferAttach = intelHandleBufferAttach,