*
**************************************************************************/
-#include "glheader.h"
-#include "context.h"
-#include "framebuffer.h"
-#include "matrix.h"
-#include "renderbuffer.h"
-#include "simple_list.h"
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "main/texobj.h"
+#include "main/hash.h"
+#include "main/fbobject.h"
+#include "main/version.h"
+#include "swrast/s_renderbuffer.h"
+
#include "utils.h"
-#include "vblank.h"
#include "xmlpool.h"
+static const __DRIconfigOptionsExtension brw_config_options = {
+ .base = { __DRI_CONFIG_OPTIONS, 1 },
+ .xml =
+DRI_CONF_BEGIN
+ DRI_CONF_SECTION_PERFORMANCE
+ DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_ALWAYS_SYNC)
+ /* Options correspond to DRI_CONF_BO_REUSE_DISABLED,
+ * DRI_CONF_BO_REUSE_ALL
+ */
+ DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1")
+ DRI_CONF_DESC_BEGIN(en, "Buffer object reuse")
+ DRI_CONF_ENUM(0, "Disable buffer object reuse")
+ DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects")
+ DRI_CONF_DESC_END
+ DRI_CONF_OPT_END
+
+ DRI_CONF_OPT_BEGIN_B(hiz, "true")
+ DRI_CONF_DESC(en, "Enable Hierarchical Z on gen6+")
+ DRI_CONF_OPT_END
+
+ DRI_CONF_OPT_BEGIN_B(disable_derivative_optimization, "false")
+ DRI_CONF_DESC(en, "Derivatives with finer granularity by default")
+ DRI_CONF_OPT_END
+ DRI_CONF_SECTION_END
+
+ DRI_CONF_SECTION_QUALITY
+ DRI_CONF_FORCE_S3TC_ENABLE("false")
+
+ DRI_CONF_OPT_BEGIN(clamp_max_samples, int, -1)
+ DRI_CONF_DESC(en, "Clamp the value of GL_MAX_SAMPLES to the "
+ "given integer. If negative, then do not clamp.")
+ DRI_CONF_OPT_END
+ DRI_CONF_SECTION_END
+
+ DRI_CONF_SECTION_DEBUG
+ DRI_CONF_NO_RAST("false")
+ DRI_CONF_ALWAYS_FLUSH_BATCH("false")
+ DRI_CONF_ALWAYS_FLUSH_CACHE("false")
+ DRI_CONF_DISABLE_THROTTLING("false")
+ DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false")
+ DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false")
+ DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false")
+
+ DRI_CONF_OPT_BEGIN_B(shader_precompile, "true")
+ DRI_CONF_DESC(en, "Perform code generation at shader link time.")
+ DRI_CONF_OPT_END
+ DRI_CONF_SECTION_END
+DRI_CONF_END
+};
+#include "intel_batchbuffer.h"
+#include "intel_buffers.h"
+#include "intel_bufmgr.h"
+#include "intel_chipset.h"
+#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
#include "intel_screen.h"
-
-#include "intel_context.h"
#include "intel_tex.h"
-#include "intel_span.h"
-#include "intel_ioctl.h"
+#include "intel_regions.h"
-#include "i830_dri.h"
+#include "brw_context.h"
-PUBLIC const char __driConfigOptions[] =
-DRI_CONF_BEGIN
- DRI_CONF_SECTION_PERFORMANCE
- DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
- DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
- DRI_CONF_SECTION_END
- DRI_CONF_SECTION_QUALITY
- DRI_CONF_FORCE_S3TC_ENABLE(false)
- DRI_CONF_ALLOW_LARGE_TEXTURES(1)
- DRI_CONF_SECTION_END
-DRI_CONF_END;
-const GLuint __driNConfigOptions = 4;
+#include "i915_drm.h"
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
-#endif /*USE_NEW_INTERFACE*/
+#endif /*USE_NEW_INTERFACE */
/**
- * Map all the memory regions described by the screen.
- * \return GL_TRUE if success, GL_FALSE if error.
+ * For debugging purposes, this returns a time in seconds.
*/
-GLboolean
-intelMapScreenRegions(__DRIscreenPrivate *sPriv)
-{
- intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
-
- if (intelScreen->front.handle) {
- if (drmMap(sPriv->fd,
- intelScreen->front.handle,
- intelScreen->front.size,
- (drmAddress *)&intelScreen->front.map) != 0) {
- _mesa_problem(NULL, "drmMap(frontbuffer) failed!");
- return GL_FALSE;
- }
- } else {
- /* Use the old static allocation method if the server isn't setting up
- * a movable handle for us. Add in the front buffer offset from
- * framebuffer start, as our span routines (unlike other drivers) expect
- * the renderbuffer address to point to the beginning of the
- * renderbuffer.
- */
- intelScreen->front.map = (char *)sPriv->pFB;
- if (intelScreen->front.map == NULL) {
- fprintf(stderr, "Failed to find framebuffer mapping\n");
- return GL_FALSE;
+double
+get_time(void)
+{
+ struct timespec tp;
+
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+
+ return tp.tv_sec + tp.tv_nsec / 1000000000.0;
+}
+
+void
+aub_dump_bmp(struct gl_context *ctx)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+ for (int i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ struct intel_renderbuffer *irb =
+ intel_renderbuffer(fb->_ColorDrawBuffers[i]);
+
+ if (irb && irb->mt) {
+ enum aub_dump_bmp_format format;
+
+ switch (irb->Base.Base.Format) {
+ case MESA_FORMAT_ARGB8888:
+ case MESA_FORMAT_XRGB8888:
+ format = AUB_DUMP_BMP_FORMAT_ARGB_8888;
+ break;
+ default:
+ continue;
+ }
+
+ assert(irb->mt->region->pitch % irb->mt->region->cpp == 0);
+ drm_intel_gem_bo_aub_dump_bmp(irb->mt->region->bo,
+ irb->draw_x,
+ irb->draw_y,
+ irb->Base.Base.Width,
+ irb->Base.Base.Height,
+ format,
+ irb->mt->region->pitch,
+ 0);
}
}
+}
- if (drmMap(sPriv->fd,
- intelScreen->back.handle,
- intelScreen->back.size,
- (drmAddress *)&intelScreen->back.map) != 0) {
- intelUnmapScreenRegions(intelScreen);
- return GL_FALSE;
- }
+static const __DRItexBufferExtension intelTexBufferExtension = {
+ .base = { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
- if (drmMap(sPriv->fd,
- intelScreen->depth.handle,
- intelScreen->depth.size,
- (drmAddress *)&intelScreen->depth.map) != 0) {
- intelUnmapScreenRegions(intelScreen);
- return GL_FALSE;
+ .setTexBuffer = intelSetTexBuffer,
+ .setTexBuffer2 = intelSetTexBuffer2,
+ .releaseTexBuffer = NULL,
+};
+
+static void
+intel_dri2_flush_with_flags(__DRIcontext *cPriv,
+ __DRIdrawable *dPriv,
+ unsigned flags,
+ enum __DRI2throttleReason reason)
+{
+ struct brw_context *brw = cPriv->driverPrivate;
+
+ if (!brw)
+ return;
+
+ struct gl_context *ctx = &brw->ctx;
+
+ FLUSH_VERTICES(ctx, 0);
+
+ if (flags & __DRI2_FLUSH_DRAWABLE)
+ intel_resolve_for_dri2_flush(brw, dPriv);
+
+ if (reason == __DRI2_THROTTLE_SWAPBUFFER ||
+ reason == __DRI2_THROTTLE_FLUSHFRONT) {
+ brw->need_throttle = true;
}
- if (drmMap(sPriv->fd,
- intelScreen->tex.handle,
- intelScreen->tex.size,
- (drmAddress *)&intelScreen->tex.map) != 0) {
- intelUnmapScreenRegions(intelScreen);
- return GL_FALSE;
+ intel_batchbuffer_flush(brw);
+
+ if (INTEL_DEBUG & DEBUG_AUB) {
+ aub_dump_bmp(ctx);
}
+}
- if (0)
- printf("Mappings: front: %p back: %p depth: %p tex: %p\n",
- intelScreen->front.map,
- intelScreen->back.map,
- intelScreen->depth.map,
- intelScreen->tex.map);
- return GL_TRUE;
+/**
+ * Provides compatibility with loaders that only support the older (version
+ * 1-3) flush interface.
+ *
+ * That includes libGL up to Mesa 9.0, and the X Server at least up to 1.13.
+ */
+static void
+intel_dri2_flush(__DRIdrawable *drawable)
+{
+ intel_dri2_flush_with_flags(drawable->driContextPriv, drawable,
+ __DRI2_FLUSH_DRAWABLE,
+ __DRI2_THROTTLE_SWAPBUFFER);
}
+static const struct __DRI2flushExtensionRec intelFlushExtension = {
+ .base = { __DRI2_FLUSH, 4 },
-void
-intelUnmapScreenRegions(intelScreenPrivate *intelScreen)
+ .flush = intel_dri2_flush,
+ .invalidate = dri2InvalidateDrawable,
+ .flush_with_flags = intel_dri2_flush_with_flags,
+};
+
+static struct intel_image_format intel_image_formats[] = {
+ { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
+
+ { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
+
+ { __DRI_IMAGE_FOURCC_RGB565, __DRI_IMAGE_COMPONENTS_RGB, 1,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } },
+
+ { __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+ { __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+ { __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+ { __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+ { __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+ { __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
+
+ { __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+ { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
+
+ /* For YUYV buffers, we set up two overlapping DRI images and treat
+ * them as planar buffers in the compositors. Plane 0 is GR88 and
+ * samples YU or YV pairs and places Y into the R component, while
+ * plane 1 is ARGB and samples YUYV clusters and places pairs and
+ * places U into the G component and V into A. This lets the
+ * texture sampler interpolate the Y components correctly when
+ * sampling from plane 0, and interpolate U and V correctly when
+ * sampling from plane 1. */
+ { __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_COMPONENTS_Y_XUXV, 2,
+ { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
+ { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }
+};
+
+static struct intel_image_format *
+intel_image_format_lookup(int fourcc)
{
-#define REALLY_UNMAP 1
- /* If front.handle is present, we're doing the dynamic front buffer mapping,
- * but if we've fallen back to static allocation then we shouldn't try to
- * unmap here.
- */
- if (intelScreen->front.handle) {
-#if REALLY_UNMAP
- if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0)
- printf("drmUnmap front failed!\n");
-#endif
- intelScreen->front.map = NULL;
- }
- if (intelScreen->back.map) {
-#if REALLY_UNMAP
- if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0)
- printf("drmUnmap back failed!\n");
-#endif
- intelScreen->back.map = NULL;
- }
- if (intelScreen->depth.map) {
-#if REALLY_UNMAP
- drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
- intelScreen->depth.map = NULL;
-#endif
- }
- if (intelScreen->tex.map) {
-#if REALLY_UNMAP
- drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
- intelScreen->tex.map = NULL;
-#endif
+ struct intel_image_format *f = NULL;
+
+ for (unsigned i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
+ if (intel_image_formats[i].fourcc == fourcc) {
+ f = &intel_image_formats[i];
+ break;
+ }
}
+
+ return f;
}
+static __DRIimage *
+intel_allocate_image(int dri_format, void *loaderPrivate)
+{
+ __DRIimage *image;
-static void
-intelPrintDRIInfo(intelScreenPrivate *intelScreen,
- __DRIscreenPrivate *sPriv,
- I830DRIPtr gDRIPriv)
-{
- fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
- intelScreen->front.size, intelScreen->front.offset,
- intelScreen->front.pitch);
- fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n",
- intelScreen->back.size, intelScreen->back.offset,
- intelScreen->back.pitch);
- fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n",
- intelScreen->depth.size, intelScreen->depth.offset,
- intelScreen->depth.pitch);
- fprintf(stderr, "*** Rotated size: 0x%x offset: 0x%x pitch: %d\n",
- intelScreen->rotated.size, intelScreen->rotated.offset,
- intelScreen->rotated.pitch);
- fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n",
- intelScreen->tex.size, intelScreen->tex.offset);
- fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
+ image = calloc(1, sizeof *image);
+ if (image == NULL)
+ return NULL;
+
+ image->dri_format = dri_format;
+ image->offset = 0;
+
+ image->format = driImageFormatToGLFormat(dri_format);
+ if (dri_format != __DRI_IMAGE_FORMAT_NONE &&
+ image->format == MESA_FORMAT_NONE) {
+ free(image);
+ return NULL;
+ }
+
+ image->internal_format = _mesa_get_format_base_format(image->format);
+ image->data = loaderPrivate;
+
+ return image;
}
+/**
+ * Sets up a DRIImage structure to point to our shared image in a region
+ */
+static void
+intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image,
+ struct intel_mipmap_tree *mt, GLuint level,
+ GLuint zoffset)
+{
+ unsigned int draw_x, draw_y;
+ uint32_t mask_x, mask_y;
+
+ intel_miptree_make_shareable(brw, mt);
+
+ intel_miptree_check_level_layer(mt, level, zoffset);
+
+ intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false);
+ intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y);
+
+ image->width = mt->level[level].width;
+ image->height = mt->level[level].height;
+ image->tile_x = draw_x & mask_x;
+ image->tile_y = draw_y & mask_y;
+
+ image->offset = intel_region_get_aligned_offset(mt->region,
+ draw_x & ~mask_x,
+ draw_y & ~mask_y,
+ false);
+
+ intel_region_reference(&image->region, mt->region);
+}
static void
-intelPrintSAREA(volatile drmI830Sarea *sarea)
-{
- fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, sarea->height);
- fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
- fprintf(stderr,
- "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
- sarea->front_offset, sarea->front_size,
- (unsigned) sarea->front_handle);
- fprintf(stderr,
- "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
- sarea->back_offset, sarea->back_size,
- (unsigned) sarea->back_handle);
- fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
- sarea->depth_offset, sarea->depth_size,
- (unsigned) sarea->depth_handle);
- fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
- sarea->tex_offset, sarea->tex_size,
- (unsigned) sarea->tex_handle);
- fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
- fprintf(stderr,
- "SAREA: rotated offset: 0x%08x size: 0x%x\n",
- sarea->rotated_offset, sarea->rotated_size);
- fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch);
+intel_setup_image_from_dimensions(__DRIimage *image)
+{
+ image->width = image->region->width;
+ image->height = image->region->height;
+ image->tile_x = 0;
+ image->tile_y = 0;
+ image->has_depthstencil = false;
}
+static __DRIimage *
+intel_create_image_from_name(__DRIscreen *screen,
+ int width, int height, int format,
+ int name, int pitch, void *loaderPrivate)
+{
+ struct intel_screen *intelScreen = screen->driverPrivate;
+ __DRIimage *image;
+ int cpp;
+
+ image = intel_allocate_image(format, loaderPrivate);
+ if (image == NULL)
+ return NULL;
+
+ if (image->format == MESA_FORMAT_NONE)
+ cpp = 1;
+ else
+ cpp = _mesa_get_format_bytes(image->format);
+ image->region = intel_region_alloc_for_handle(intelScreen,
+ cpp, width, height,
+ pitch * cpp, name, "image");
+ if (image->region == NULL) {
+ free(image);
+ return NULL;
+ }
-/**
- * A number of the screen parameters are obtained/computed from
- * information in the SAREA. This function updates those parameters.
- */
-void
-intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen,
- volatile drmI830Sarea *sarea)
-{
- intelScreen->width = sarea->width;
- intelScreen->height = sarea->height;
-
- intelScreen->front.offset = sarea->front_offset;
- intelScreen->front.pitch = sarea->pitch * intelScreen->cpp;
- intelScreen->front.handle = sarea->front_handle;
- intelScreen->front.size = sarea->front_size;
- intelScreen->front.tiled = sarea->front_tiled;
-
- intelScreen->back.offset = sarea->back_offset;
- intelScreen->back.pitch = sarea->pitch * intelScreen->cpp;
- intelScreen->back.handle = sarea->back_handle;
- intelScreen->back.size = sarea->back_size;
- intelScreen->back.tiled = sarea->back_tiled;
-
- intelScreen->depth.offset = sarea->depth_offset;
- intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp;
- intelScreen->depth.handle = sarea->depth_handle;
- intelScreen->depth.size = sarea->depth_size;
- intelScreen->depth.tiled = sarea->depth_tiled;
-
- intelScreen->tex.offset = sarea->tex_offset;
- intelScreen->logTextureGranularity = sarea->log_tex_granularity;
- intelScreen->tex.handle = sarea->tex_handle;
- intelScreen->tex.size = sarea->tex_size;
-
- intelScreen->rotated.offset = sarea->rotated_offset;
- intelScreen->rotated.pitch = sarea->rotated_pitch * intelScreen->cpp;
- intelScreen->rotated.size = sarea->rotated_size;
- intelScreen->rotated.tiled = sarea->rotated_tiled;
- intelScreen->current_rotation = sarea->rotation;
-#if 0
- matrix23Rotate(&intelScreen->rotMatrix,
- sarea->width, sarea->height, sarea->rotation);
-#endif
- intelScreen->rotatedWidth = sarea->virtualX;
- intelScreen->rotatedHeight = sarea->virtualY;
-
- if (0)
- intelPrintSAREA(sarea);
-}
-
-
-static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
-{
- intelScreenPrivate *intelScreen;
- I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv;
- PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
- (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension"));
- void * const psc = sPriv->psc->screenConfigs;
- volatile drmI830Sarea *sarea;
-
- if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
- fprintf(stderr,"\nERROR! sizeof(I830DRIRec) (%ld) does not match passed size from device driver (%d)\n", (unsigned long)sizeof(I830DRIRec), sPriv->devPrivSize);
- return GL_FALSE;
+ intel_setup_image_from_dimensions(image);
+
+ return image;
+}
+
+static __DRIimage *
+intel_create_image_from_renderbuffer(__DRIcontext *context,
+ int renderbuffer, void *loaderPrivate)
+{
+ __DRIimage *image;
+ struct brw_context *brw = context->driverPrivate;
+ struct gl_context *ctx = &brw->ctx;
+ struct gl_renderbuffer *rb;
+ struct intel_renderbuffer *irb;
+
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
+ return NULL;
}
- /* Allocate the private area */
- intelScreen = (intelScreenPrivate *)CALLOC(sizeof(intelScreenPrivate));
- if (!intelScreen) {
- fprintf(stderr,"\nERROR! Allocating private area failed\n");
- return GL_FALSE;
+ irb = intel_renderbuffer(rb);
+ intel_miptree_make_shareable(brw, irb->mt);
+ image = calloc(1, sizeof *image);
+ if (image == NULL)
+ return NULL;
+
+ image->internal_format = rb->InternalFormat;
+ image->format = rb->Format;
+ image->offset = 0;
+ image->data = loaderPrivate;
+ intel_region_reference(&image->region, irb->mt->region);
+ intel_setup_image_from_dimensions(image);
+ image->dri_format = driGLFormatToImageFormat(image->format);
+ image->has_depthstencil = irb->mt->stencil_mt? true : false;
+
+ rb->NeedsFinishRenderTexture = true;
+ return image;
+}
+
+static __DRIimage *
+intel_create_image_from_texture(__DRIcontext *context, int target,
+ unsigned texture, int zoffset,
+ int level,
+ unsigned *error,
+ void *loaderPrivate)
+{
+ __DRIimage *image;
+ struct brw_context *brw = context->driverPrivate;
+ struct gl_texture_object *obj;
+ struct intel_texture_object *iobj;
+ GLuint face = 0;
+
+ obj = _mesa_lookup_texture(&brw->ctx, texture);
+ if (!obj || obj->Target != target) {
+ *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+ return NULL;
}
- /* parse information in __driConfigOptions */
- driParseOptionInfo (&intelScreen->optionCache,
- __driConfigOptions, __driNConfigOptions);
- intelScreen->driScrnPriv = sPriv;
- sPriv->private = (void *)intelScreen;
- intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
- sarea = (volatile drmI830Sarea *)
- (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
+ if (target == GL_TEXTURE_CUBE_MAP)
+ face = zoffset;
- intelScreen->deviceID = gDRIPriv->deviceID;
- intelScreen->mem = gDRIPriv->mem;
- intelScreen->cpp = gDRIPriv->cpp;
+ _mesa_test_texobj_completeness(&brw->ctx, obj);
+ iobj = intel_texture_object(obj);
+ if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
+ *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+ return NULL;
+ }
- switch (gDRIPriv->bitsPerPixel) {
- case 15: intelScreen->fbFormat = DV_PF_555; break;
- case 16: intelScreen->fbFormat = DV_PF_565; break;
- case 32: intelScreen->fbFormat = DV_PF_8888; break;
+ if (level < obj->BaseLevel || level > obj->_MaxLevel) {
+ *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+ return NULL;
}
-
- intelUpdateScreenFromSAREA(intelScreen, sarea);
- if (0)
- intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
+ if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < zoffset) {
+ *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+ return NULL;
+ }
+ image = calloc(1, sizeof *image);
+ if (image == NULL) {
+ *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
+ return NULL;
+ }
- if (!intelMapScreenRegions(sPriv)) {
- fprintf(stderr,"\nERROR! mapping regions\n");
- _mesa_free(intelScreen);
- sPriv->private = NULL;
- return GL_FALSE;
+ image->internal_format = obj->Image[face][level]->InternalFormat;
+ image->format = obj->Image[face][level]->TexFormat;
+ image->data = loaderPrivate;
+ intel_setup_image_from_mipmap_tree(brw, image, iobj->mt, level, zoffset);
+ image->dri_format = driGLFormatToImageFormat(image->format);
+ image->has_depthstencil = iobj->mt->stencil_mt? true : false;
+ if (image->dri_format == MESA_FORMAT_NONE) {
+ *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+ free(image);
+ return NULL;
}
- intelScreen->drmMinor = sPriv->drmMinor;
+ *error = __DRI_IMAGE_ERROR_SUCCESS;
+ return image;
+}
- /* Determine if IRQs are active? */
- {
- int ret;
- drmI830GetParam gp;
+static void
+intel_destroy_image(__DRIimage *image)
+{
+ intel_region_release(&image->region);
+ free(image);
+}
- gp.param = I830_PARAM_IRQ_ACTIVE;
- gp.value = &intelScreen->irq_active;
+static __DRIimage *
+intel_create_image(__DRIscreen *screen,
+ int width, int height, int format,
+ unsigned int use,
+ void *loaderPrivate)
+{
+ __DRIimage *image;
+ struct intel_screen *intelScreen = screen->driverPrivate;
+ uint32_t tiling;
+ int cpp;
+
+ tiling = I915_TILING_X;
+ if (use & __DRI_IMAGE_USE_CURSOR) {
+ if (width != 64 || height != 64)
+ return NULL;
+ tiling = I915_TILING_NONE;
+ }
- ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
- &gp, sizeof(gp));
- if (ret) {
- fprintf(stderr, "drmI830GetParam: %d\n", ret);
- return GL_FALSE;
- }
+ if (use & __DRI_IMAGE_USE_LINEAR)
+ tiling = I915_TILING_NONE;
+
+ image = intel_allocate_image(format, loaderPrivate);
+ if (image == NULL)
+ return NULL;
+
+ cpp = _mesa_get_format_bytes(image->format);
+ image->region =
+ intel_region_alloc(intelScreen, tiling, cpp, width, height, true);
+ if (image->region == NULL) {
+ free(image);
+ return NULL;
}
+
+ intel_setup_image_from_dimensions(image);
- /* Determine if batchbuffers are allowed */
- {
- int ret;
- drmI830GetParam gp;
+ return image;
+}
- gp.param = I830_PARAM_ALLOW_BATCHBUFFER;
- gp.value = &intelScreen->allow_batchbuffer;
+static GLboolean
+intel_query_image(__DRIimage *image, int attrib, int *value)
+{
+ switch (attrib) {
+ case __DRI_IMAGE_ATTRIB_STRIDE:
+ *value = image->region->pitch;
+ return true;
+ case __DRI_IMAGE_ATTRIB_HANDLE:
+ *value = image->region->bo->handle;
+ return true;
+ case __DRI_IMAGE_ATTRIB_NAME:
+ return intel_region_flink(image->region, (uint32_t *) value);
+ case __DRI_IMAGE_ATTRIB_FORMAT:
+ *value = image->dri_format;
+ return true;
+ case __DRI_IMAGE_ATTRIB_WIDTH:
+ *value = image->region->width;
+ return true;
+ case __DRI_IMAGE_ATTRIB_HEIGHT:
+ *value = image->region->height;
+ return true;
+ case __DRI_IMAGE_ATTRIB_COMPONENTS:
+ if (image->planar_format == NULL)
+ return false;
+ *value = image->planar_format->components;
+ return true;
+ case __DRI_IMAGE_ATTRIB_FD:
+ if (drm_intel_bo_gem_export_to_prime(image->region->bo, value) == 0)
+ return true;
+ return false;
+ default:
+ return false;
+ }
+}
- ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
- &gp, sizeof(gp));
- if (ret) {
- fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret);
- return GL_FALSE;
- }
+static __DRIimage *
+intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
+{
+ __DRIimage *image;
+
+ image = calloc(1, sizeof *image);
+ if (image == NULL)
+ return NULL;
+
+ intel_region_reference(&image->region, orig_image->region);
+ if (image->region == NULL) {
+ free(image);
+ return NULL;
}
- if (glx_enable_extension != NULL) {
- (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
- (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
- (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
- (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
- (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
- (*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" );
+ image->internal_format = orig_image->internal_format;
+ image->planar_format = orig_image->planar_format;
+ image->dri_format = orig_image->dri_format;
+ image->format = orig_image->format;
+ image->offset = orig_image->offset;
+ image->width = orig_image->width;
+ image->height = orig_image->height;
+ image->tile_x = orig_image->tile_x;
+ image->tile_y = orig_image->tile_y;
+ image->has_depthstencil = orig_image->has_depthstencil;
+ image->data = loaderPrivate;
+
+ memcpy(image->strides, orig_image->strides, sizeof(image->strides));
+ memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets));
+
+ return image;
+}
+
+static GLboolean
+intel_validate_usage(__DRIimage *image, unsigned int use)
+{
+ if (use & __DRI_IMAGE_USE_CURSOR) {
+ if (image->region->width != 64 || image->region->height != 64)
+ return GL_FALSE;
}
-
+
return GL_TRUE;
}
-
-static void intelDestroyScreen(__DRIscreenPrivate *sPriv)
+static __DRIimage *
+intel_create_image_from_names(__DRIscreen *screen,
+ int width, int height, int fourcc,
+ int *names, int num_names,
+ int *strides, int *offsets,
+ void *loaderPrivate)
{
- intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
+ struct intel_image_format *f = NULL;
+ __DRIimage *image;
+ int i, index;
+
+ if (screen == NULL || names == NULL || num_names != 1)
+ return NULL;
+
+ f = intel_image_format_lookup(fourcc);
+ if (f == NULL)
+ return NULL;
+
+ image = intel_create_image_from_name(screen, width, height,
+ __DRI_IMAGE_FORMAT_NONE,
+ names[0], strides[0],
+ loaderPrivate);
+
+ if (image == NULL)
+ return NULL;
+
+ image->planar_format = f;
+ for (i = 0; i < f->nplanes; i++) {
+ index = f->planes[i].buffer_index;
+ image->offsets[index] = offsets[index];
+ image->strides[index] = strides[index];
+ }
- intelUnmapScreenRegions(intelScreen);
- FREE(intelScreen);
- sPriv->private = NULL;
+ return image;
}
-static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
- __DRIdrawablePrivate *driDrawPriv,
- const __GLcontextModes *mesaVis,
- GLboolean isPixmap )
+static __DRIimage *
+intel_create_image_from_fds(__DRIscreen *screen,
+ int width, int height, int fourcc,
+ int *fds, int num_fds, int *strides, int *offsets,
+ void *loaderPrivate)
{
- intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
+ struct intel_screen *intelScreen = screen->driverPrivate;
+ struct intel_image_format *f;
+ __DRIimage *image;
+ int i, index;
- if (isPixmap) {
- return GL_FALSE; /* not implemented */
- } else {
- GLboolean swStencil = (mesaVis->stencilBits > 0 &&
- mesaVis->depthBits != 24);
+ if (fds == NULL || num_fds != 1)
+ return NULL;
- struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
+ f = intel_image_format_lookup(fourcc);
+ if (f == NULL)
+ return NULL;
- {
- driRenderbuffer *frontRb
- = driNewRenderbuffer(GL_RGBA,
- screen->front.map,
- screen->cpp,
- screen->front.offset, screen->front.pitch,
- driDrawPriv);
- intelSetSpanFunctions(frontRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
- }
+ if (f->nplanes == 1)
+ image = intel_allocate_image(f->planes[0].dri_format, loaderPrivate);
+ else
+ image = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPrivate);
- if (mesaVis->doubleBufferMode) {
- driRenderbuffer *backRb
- = driNewRenderbuffer(GL_RGBA,
- screen->back.map,
- screen->cpp,
- screen->back.offset, screen->back.pitch,
- driDrawPriv);
- intelSetSpanFunctions(backRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
- }
+ if (image == NULL)
+ return NULL;
- if (mesaVis->depthBits == 16) {
- driRenderbuffer *depthRb
- = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
- screen->depth.map,
- screen->cpp,
- screen->depth.offset, screen->depth.pitch,
- driDrawPriv);
- intelSetSpanFunctions(depthRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
- }
- else if (mesaVis->depthBits == 24) {
- driRenderbuffer *depthRb
- = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
- screen->depth.map,
- screen->cpp,
- screen->depth.offset, screen->depth.pitch,
- driDrawPriv);
- intelSetSpanFunctions(depthRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
- }
+ image->region = intel_region_alloc_for_fd(intelScreen,
+ f->planes[0].cpp, width, height, strides[0],
+ height * strides[0], fds[0], "image");
+ if (image->region == NULL) {
+ free(image);
+ return NULL;
+ }
- if (mesaVis->stencilBits > 0 && !swStencil) {
- driRenderbuffer *stencilRb
- = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
- screen->depth.map,
- screen->cpp,
- screen->depth.offset, screen->depth.pitch,
- driDrawPriv);
- intelSetSpanFunctions(stencilRb, mesaVis);
- _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
- }
+ image->planar_format = f;
+ for (i = 0; i < f->nplanes; i++) {
+ index = f->planes[i].buffer_index;
+ image->offsets[index] = offsets[index];
+ image->strides[index] = strides[index];
+ }
+
+ intel_setup_image_from_dimensions(image);
+
+ return image;
+}
+
+static __DRIimage *
+intel_create_image_from_dma_bufs(__DRIscreen *screen,
+ int width, int height, int fourcc,
+ int *fds, int num_fds,
+ int *strides, int *offsets,
+ enum __DRIYUVColorSpace yuv_color_space,
+ enum __DRISampleRange sample_range,
+ enum __DRIChromaSiting horizontal_siting,
+ enum __DRIChromaSiting vertical_siting,
+ unsigned *error,
+ void *loaderPrivate)
+{
+ __DRIimage *image;
+ struct intel_image_format *f = intel_image_format_lookup(fourcc);
- _mesa_add_soft_renderbuffers(fb,
- GL_FALSE, /* color */
- GL_FALSE, /* depth */
- swStencil,
- mesaVis->accumRedBits > 0,
- GL_FALSE, /* alpha */
- GL_FALSE /* aux */);
- driDrawPriv->driverPrivate = (void *) fb;
+ /* For now only packed formats that have native sampling are supported. */
+ if (!f || f->nplanes != 1) {
+ *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+ return NULL;
+ }
- return (driDrawPriv->driverPrivate != NULL);
+ image = intel_create_image_from_fds(screen, width, height, fourcc, fds,
+ num_fds, strides, offsets,
+ loaderPrivate);
+
+ /*
+ * Invalid parameters and any inconsistencies between are assumed to be
+ * checked by the caller. Therefore besides unsupported formats one can fail
+ * only in allocation.
+ */
+ if (!image) {
+ *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
+ return NULL;
}
+
+ image->dma_buf_imported = true;
+ image->yuv_color_space = yuv_color_space;
+ image->sample_range = sample_range;
+ image->horizontal_siting = horizontal_siting;
+ image->vertical_siting = vertical_siting;
+
+ *error = __DRI_IMAGE_ERROR_SUCCESS;
+ return image;
}
-static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+static __DRIimage *
+intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate)
{
- _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+ int width, height, offset, stride, dri_format, index;
+ struct intel_image_format *f;
+ uint32_t mask_x, mask_y;
+ __DRIimage *image;
+
+ if (parent == NULL || parent->planar_format == NULL)
+ return NULL;
+
+ f = parent->planar_format;
+
+ if (plane >= f->nplanes)
+ return NULL;
+
+ width = parent->region->width >> f->planes[plane].width_shift;
+ height = parent->region->height >> f->planes[plane].height_shift;
+ dri_format = f->planes[plane].dri_format;
+ index = f->planes[plane].buffer_index;
+ offset = parent->offsets[index];
+ stride = parent->strides[index];
+
+ image = intel_allocate_image(dri_format, loaderPrivate);
+ if (image == NULL)
+ return NULL;
+
+ if (offset + height * stride > parent->region->bo->size) {
+ _mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds");
+ free(image);
+ return NULL;
+ }
+
+ image->region = calloc(sizeof(*image->region), 1);
+ if (image->region == NULL) {
+ free(image);
+ return NULL;
+ }
+
+ image->region->cpp = _mesa_get_format_bytes(image->format);
+ image->region->width = width;
+ image->region->height = height;
+ image->region->pitch = stride;
+ image->region->refcount = 1;
+ image->region->bo = parent->region->bo;
+ drm_intel_bo_reference(image->region->bo);
+ image->region->tiling = parent->region->tiling;
+ image->offset = offset;
+ intel_setup_image_from_dimensions(image);
+
+ intel_region_get_tile_masks(image->region, &mask_x, &mask_y, false);
+ if (offset & mask_x)
+ _mesa_warning(NULL,
+ "intel_create_sub_image: offset not on tile boundary");
+
+ return image;
}
+static struct __DRIimageExtensionRec intelImageExtension = {
+ .base = { __DRI_IMAGE, 8 },
+
+ .createImageFromName = intel_create_image_from_name,
+ .createImageFromRenderbuffer = intel_create_image_from_renderbuffer,
+ .destroyImage = intel_destroy_image,
+ .createImage = intel_create_image,
+ .queryImage = intel_query_image,
+ .dupImage = intel_dup_image,
+ .validateUsage = intel_validate_usage,
+ .createImageFromNames = intel_create_image_from_names,
+ .fromPlanar = intel_from_planar,
+ .createImageFromTexture = intel_create_image_from_texture,
+ .createImageFromFds = intel_create_image_from_fds,
+ .createImageFromDmaBufs = intel_create_image_from_dma_bufs
+};
-/**
- * Get information about previous buffer swaps.
- */
static int
-intelGetSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
+brw_query_renderer_integer(__DRIscreen *psp, int param, unsigned int *value)
{
- struct intel_context *intel;
+ const struct intel_screen *const intelScreen =
+ (struct intel_screen *) psp->driverPrivate;
+
+ switch (param) {
+ case __DRI2_RENDERER_VENDOR_ID:
+ value[0] = 0x8086;
+ return 0;
+ case __DRI2_RENDERER_DEVICE_ID:
+ value[0] = intelScreen->deviceID;
+ return 0;
+ case __DRI2_RENDERER_ACCELERATED:
+ value[0] = 1;
+ return 0;
+ case __DRI2_RENDERER_VIDEO_MEMORY: {
+ /* Once a batch uses more than 75% of the maximum mappable size, we
+ * assume that there's some fragmentation, and we start doing extra
+ * flushing, etc. That's the big cliff apps will care about.
+ */
+ size_t aper_size;
+ size_t mappable_size;
+
+ drm_intel_get_aperture_sizes(psp->fd, &mappable_size, &aper_size);
+
+ const unsigned gpu_mappable_megabytes =
+ (aper_size / (1024 * 1024)) * 3 / 4;
+
+ const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
+ const long system_page_size = sysconf(_SC_PAGE_SIZE);
- if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
- || (dPriv->driContextPriv->driverPrivate == NULL)
- || (sInfo == NULL) ) {
- return -1;
+ if (system_memory_pages <= 0 || system_page_size <= 0)
+ return -1;
+
+ const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
+ * (uint64_t) system_page_size;
+
+ const unsigned system_memory_megabytes =
+ (unsigned) (system_memory_bytes / 1024);
+
+ value[0] = MIN2(system_memory_megabytes, gpu_mappable_megabytes);
+ return 0;
+ }
+ case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
+ value[0] = 1;
+ return 0;
+ case __DRI2_RENDERER_PREFERRED_PROFILE:
+ value[0] = (psp->max_gl_core_version != 0)
+ ? (1U << __DRI_API_OPENGL_CORE) : (1U << __DRI_API_OPENGL);
+ return 0;
+ default:
+ return driQueryRendererIntegerCommon(psp, param, value);
}
- intel = dPriv->driContextPriv->driverPrivate;
- sInfo->swap_count = intel->swap_count;
- sInfo->swap_ust = intel->swap_ust;
- sInfo->swap_missed_count = intel->swap_missed_count;
+ return -1;
+}
- sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
- ? driCalculateSwapUsage( dPriv, 0, intel->swap_missed_ust )
- : 0.0;
+static int
+brw_query_renderer_string(__DRIscreen *psp, int param, const char **value)
+{
+ const struct intel_screen *intelScreen =
+ (struct intel_screen *) psp->driverPrivate;
+
+ switch (param) {
+ case __DRI2_RENDERER_VENDOR_ID:
+ value[0] = brw_vendor_string;
+ return 0;
+ case __DRI2_RENDERER_DEVICE_ID:
+ value[0] = brw_get_renderer_string(intelScreen->deviceID);
+ return 0;
+ default:
+ break;
+ }
- return 0;
+ return -1;
}
+static struct __DRI2rendererQueryExtensionRec intelRendererQueryExtension = {
+ .base = { __DRI2_RENDERER_QUERY, 1 },
-/* There are probably better ways to do this, such as an
- * init-designated function to register chipids and createcontext
- * functions.
- */
-extern GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
- __DRIcontextPrivate *driContextPriv,
- void *sharedContextPrivate);
-
-extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
- __DRIcontextPrivate *driContextPriv,
- void *sharedContextPrivate);
-
-extern GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
- __DRIcontextPrivate *driContextPriv,
- void *sharedContextPrivate);
-
-
-
-
-static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
- __DRIcontextPrivate *driContextPriv,
- void *sharedContextPrivate)
-{
-#if 0
- __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
- intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
- switch (intelScreen->deviceID) {
- case PCI_CHIP_845_G:
- case PCI_CHIP_I830_M:
- case PCI_CHIP_I855_GM:
- case PCI_CHIP_I865_G:
- return i830CreateContext( mesaVis, driContextPriv,
- sharedContextPrivate );
-
- case PCI_CHIP_I915_G:
- case PCI_CHIP_I915_GM:
- case PCI_CHIP_I945_G:
- case PCI_CHIP_I945_GM:
- return i915CreateContext( mesaVis, driContextPriv,
- sharedContextPrivate );
-
- default:
- fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
- return GL_FALSE;
- }
-#else
- return brwCreateContext( mesaVis, driContextPriv,
- sharedContextPrivate );
-#endif
-}
-
-
-static const struct __DriverAPIRec intelAPI = {
- .InitDriver = intelInitDriver,
- .DestroyScreen = intelDestroyScreen,
- .CreateContext = intelCreateContext,
- .DestroyContext = intelDestroyContext,
- .CreateBuffer = intelCreateBuffer,
- .DestroyBuffer = intelDestroyBuffer,
- .SwapBuffers = intelSwapBuffers,
- .MakeCurrent = intelMakeCurrent,
- .UnbindContext = intelUnbindContext,
- .GetSwapInfo = intelGetSwapInfo,
- .GetMSC = driGetMSC32,
- .WaitForMSC = driWaitForMSC32,
- .WaitForSBC = NULL,
- .SwapBuffersMSC = NULL,
- .CopySubBuffer = intelCopySubBuffer
+ .queryInteger = brw_query_renderer_integer,
+ .queryString = brw_query_renderer_string
};
+static const struct __DRIrobustnessExtensionRec dri2Robustness = {
+ { __DRI2_ROBUSTNESS, 1 }
+};
-static __GLcontextModes *
-intelFillInModes( unsigned pixel_bits, unsigned depth_bits,
- unsigned stencil_bits, GLboolean have_back_buffer )
+static const __DRIextension *intelScreenExtensions[] = {
+ &intelTexBufferExtension.base,
+ &intelFlushExtension.base,
+ &intelImageExtension.base,
+ &intelRendererQueryExtension.base,
+ &dri2ConfigQueryExtension.base,
+ &dri2Robustness.base,
+ NULL
+};
+
+static bool
+intel_get_param(__DRIscreen *psp, int param, int *value)
{
- __GLcontextModes * modes;
- __GLcontextModes * m;
- unsigned num_modes;
- unsigned depth_buffer_factor;
- unsigned back_buffer_factor;
- GLenum fb_format;
- GLenum fb_type;
+ int ret;
+ struct drm_i915_getparam gp;
+
+ memset(&gp, 0, sizeof(gp));
+ gp.param = param;
+ gp.value = value;
+
+ ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
+ if (ret) {
+ if (ret != -EINVAL)
+ _mesa_warning(NULL, "drm_i915_getparam: %d", ret);
+ return false;
+ }
- /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
- * support pageflipping at all.
- */
- static const GLenum back_buffer_modes[] = {
- GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
- };
+ return true;
+}
+
+static bool
+intel_get_boolean(__DRIscreen *psp, int param)
+{
+ int value = 0;
+ return intel_get_param(psp, param, &value) && value;
+}
+
+static void
+intelDestroyScreen(__DRIscreen * sPriv)
+{
+ struct intel_screen *intelScreen = sPriv->driverPrivate;
+
+ dri_bufmgr_destroy(intelScreen->bufmgr);
+ driDestroyOptionInfo(&intelScreen->optionCache);
- uint8_t depth_bits_array[3];
- uint8_t stencil_bits_array[3];
+ free(intelScreen);
+ sPriv->driverPrivate = NULL;
+}
- depth_bits_array[0] = 0;
- depth_bits_array[1] = depth_bits;
- depth_bits_array[2] = depth_bits;
+/**
+ * This is called when we need to set up GL rendering to a new X window.
+ */
+static GLboolean
+intelCreateBuffer(__DRIscreen * driScrnPriv,
+ __DRIdrawable * driDrawPriv,
+ const struct gl_config * mesaVis, GLboolean isPixmap)
+{
+ struct intel_renderbuffer *rb;
+ struct intel_screen *screen = (struct intel_screen*) driScrnPriv->driverPrivate;
+ gl_format rgbFormat;
+ unsigned num_samples = intel_quantize_num_samples(screen, mesaVis->samples);
+ struct gl_framebuffer *fb;
+
+ if (isPixmap)
+ return false;
+
+ fb = CALLOC_STRUCT(gl_framebuffer);
+ if (!fb)
+ return false;
+
+ _mesa_initialize_window_framebuffer(fb, mesaVis);
+
+ if (mesaVis->redBits == 5)
+ rgbFormat = MESA_FORMAT_RGB565;
+ else if (mesaVis->sRGBCapable)
+ rgbFormat = MESA_FORMAT_SARGB8;
+ else if (mesaVis->alphaBits == 0)
+ rgbFormat = MESA_FORMAT_XRGB8888;
+ else {
+ rgbFormat = MESA_FORMAT_SARGB8;
+ fb->Visual.sRGBCapable = true;
+ }
- /* Just like with the accumulation buffer, always provide some modes
- * with a stencil buffer. It will be a sw fallback, but some apps won't
- * care about that.
+ /* setup the hardware-based renderbuffers */
+ rb = intel_create_renderbuffer(rgbFormat, num_samples);
+ _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base.Base);
+
+ if (mesaVis->doubleBufferMode) {
+ rb = intel_create_renderbuffer(rgbFormat, num_samples);
+ _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base.Base);
+ }
+
+ /*
+ * Assert here that the gl_config has an expected depth/stencil bit
+ * combination: one of d24/s8, d16/s0, d0/s0. (See intelInitScreen2(),
+ * which constructs the advertised configs.)
*/
- stencil_bits_array[0] = 0;
- stencil_bits_array[1] = 0;
- stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+ if (mesaVis->depthBits == 24) {
+ assert(mesaVis->stencilBits == 8);
+
+ if (screen->devinfo->has_hiz_and_separate_stencil) {
+ rb = intel_create_private_renderbuffer(MESA_FORMAT_X8_Z24,
+ num_samples);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
+ rb = intel_create_private_renderbuffer(MESA_FORMAT_S8,
+ num_samples);
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base);
+ } else {
+ /*
+ * Use combined depth/stencil. Note that the renderbuffer is
+ * attached to two attachment points.
+ */
+ rb = intel_create_private_renderbuffer(MESA_FORMAT_S8_Z24,
+ num_samples);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base);
+ }
+ }
+ else if (mesaVis->depthBits == 16) {
+ assert(mesaVis->stencilBits == 0);
+ rb = intel_create_private_renderbuffer(MESA_FORMAT_Z16,
+ num_samples);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
+ }
+ else {
+ assert(mesaVis->depthBits == 0);
+ assert(mesaVis->stencilBits == 0);
+ }
- depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
- back_buffer_factor = (have_back_buffer) ? 3 : 1;
+ /* now add any/all software-based renderbuffers we may need */
+ _swrast_add_soft_renderbuffers(fb,
+ false, /* never sw color */
+ false, /* never sw depth */
+ false, /* never sw stencil */
+ mesaVis->accumRedBits > 0,
+ false, /* never sw alpha */
+ false /* never sw aux */ );
+ driDrawPriv->driverPrivate = fb;
+
+ return true;
+}
- num_modes = depth_buffer_factor * back_buffer_factor * 4;
+static void
+intelDestroyBuffer(__DRIdrawable * driDrawPriv)
+{
+ struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
+
+ _mesa_reference_framebuffer(&fb, NULL);
+}
- if ( pixel_bits == 16 ) {
- fb_format = GL_RGB;
- fb_type = GL_UNSIGNED_SHORT_5_6_5;
- }
- else {
- fb_format = GL_BGRA;
- fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
- }
+static bool
+intel_init_bufmgr(struct intel_screen *intelScreen)
+{
+ __DRIscreen *spriv = intelScreen->driScrnPriv;
- modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
- m = modes;
- if ( ! driFillInModes( & m, fb_format, fb_type,
- depth_bits_array, stencil_bits_array, depth_buffer_factor,
- back_buffer_modes, back_buffer_factor,
- GLX_TRUE_COLOR ) ) {
- fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
- __func__, __LINE__ );
- return NULL;
+ intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL;
+
+ intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ);
+ if (intelScreen->bufmgr == NULL) {
+ fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
+ __func__, __LINE__);
+ return false;
}
- if ( ! driFillInModes( & m, fb_format, fb_type,
- depth_bits_array, stencil_bits_array, depth_buffer_factor,
- back_buffer_modes, back_buffer_factor,
- GLX_DIRECT_COLOR ) ) {
- fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
- __func__, __LINE__ );
- return NULL;
+
+ drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr);
+
+ if (!intel_get_boolean(spriv, I915_PARAM_HAS_RELAXED_DELTA)) {
+ fprintf(stderr, "[%s: %u] Kernel 2.6.39 required.\n", __func__, __LINE__);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+intel_detect_swizzling(struct intel_screen *screen)
+{
+ drm_intel_bo *buffer;
+ unsigned long flags = 0;
+ unsigned long aligned_pitch;
+ uint32_t tiling = I915_TILING_X;
+ uint32_t swizzle_mode = 0;
+
+ buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "swizzle test",
+ 64, 64, 4,
+ &tiling, &aligned_pitch, flags);
+ if (buffer == NULL)
+ return false;
+
+ drm_intel_bo_get_tiling(buffer, &tiling, &swizzle_mode);
+ drm_intel_bo_unreference(buffer);
+
+ if (swizzle_mode == I915_BIT_6_SWIZZLE_NONE)
+ return false;
+ else
+ return true;
+}
+
+static __DRIconfig**
+intel_screen_make_configs(__DRIscreen *dri_screen)
+{
+ static const gl_format formats[] = {
+ MESA_FORMAT_RGB565,
+ MESA_FORMAT_ARGB8888
+ };
+
+ /* GLX_SWAP_COPY_OML is not supported due to page flipping. */
+ static const GLenum back_buffer_modes[] = {
+ GLX_SWAP_UNDEFINED_OML, GLX_NONE,
+ };
+
+ static const uint8_t singlesample_samples[1] = {0};
+ static const uint8_t multisample_samples[2] = {4, 8};
+
+ struct intel_screen *screen = dri_screen->driverPrivate;
+ const struct brw_device_info *devinfo = screen->devinfo;
+ uint8_t depth_bits[4], stencil_bits[4];
+ __DRIconfig **configs = NULL;
+
+ /* Generate singlesample configs without accumulation buffer. */
+ for (int i = 0; i < ARRAY_SIZE(formats); i++) {
+ __DRIconfig **new_configs;
+ int num_depth_stencil_bits = 2;
+
+ /* Starting with DRI2 protocol version 1.1 we can request a depth/stencil
+ * buffer that has a different number of bits per pixel than the color
+ * buffer, gen >= 6 supports this.
+ */
+ depth_bits[0] = 0;
+ stencil_bits[0] = 0;
+
+ if (formats[i] == MESA_FORMAT_RGB565) {
+ depth_bits[1] = 16;
+ stencil_bits[1] = 0;
+ if (devinfo->gen >= 6) {
+ depth_bits[2] = 24;
+ stencil_bits[2] = 8;
+ num_depth_stencil_bits = 3;
+ }
+ } else {
+ depth_bits[1] = 24;
+ stencil_bits[1] = 8;
+ }
+
+ new_configs = driCreateConfigs(formats[i],
+ depth_bits,
+ stencil_bits,
+ num_depth_stencil_bits,
+ back_buffer_modes, 2,
+ singlesample_samples, 1,
+ false);
+ configs = driConcatConfigs(configs, new_configs);
}
- /* Mark the visual as slow if there are "fake" stencil bits.
+ /* Generate the minimum possible set of configs that include an
+ * accumulation buffer.
*/
- for ( m = modes ; m != NULL ; m = m->next ) {
- if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
- m->visualRating = GLX_SLOW_CONFIG;
+ for (int i = 0; i < ARRAY_SIZE(formats); i++) {
+ __DRIconfig **new_configs;
+
+ if (formats[i] == MESA_FORMAT_RGB565) {
+ depth_bits[0] = 16;
+ stencil_bits[0] = 0;
+ } else {
+ depth_bits[0] = 24;
+ stencil_bits[0] = 8;
}
+
+ new_configs = driCreateConfigs(formats[i],
+ depth_bits, stencil_bits, 1,
+ back_buffer_modes, 1,
+ singlesample_samples, 1,
+ true);
+ configs = driConcatConfigs(configs, new_configs);
}
- return modes;
+ /* Generate multisample configs.
+ *
+ * This loop breaks early, and hence is a no-op, on gen < 6.
+ *
+ * Multisample configs must follow the singlesample configs in order to
+ * work around an X server bug present in 1.12. The X server chooses to
+ * associate the first listed RGBA888-Z24S8 config, regardless of its
+ * sample count, with the 32-bit depth visual used for compositing.
+ *
+ * Only doublebuffer configs with GLX_SWAP_UNDEFINED_OML behavior are
+ * supported. Singlebuffer configs are not supported because no one wants
+ * them.
+ */
+ for (int i = 0; i < ARRAY_SIZE(formats); i++) {
+ if (devinfo->gen < 6)
+ break;
+
+ __DRIconfig **new_configs;
+ const int num_depth_stencil_bits = 2;
+ int num_msaa_modes = 0;
+
+ depth_bits[0] = 0;
+ stencil_bits[0] = 0;
+
+ if (formats[i] == MESA_FORMAT_RGB565) {
+ depth_bits[1] = 16;
+ stencil_bits[1] = 0;
+ } else {
+ depth_bits[1] = 24;
+ stencil_bits[1] = 8;
+ }
+
+ if (devinfo->gen >= 7)
+ num_msaa_modes = 2;
+ else if (devinfo->gen == 6)
+ num_msaa_modes = 1;
+
+ new_configs = driCreateConfigs(formats[i],
+ depth_bits,
+ stencil_bits,
+ num_depth_stencil_bits,
+ back_buffer_modes, 1,
+ multisample_samples,
+ num_msaa_modes,
+ false);
+ configs = driConcatConfigs(configs, new_configs);
+ }
+
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ __LINE__);
+ return NULL;
+ }
+
+ return configs;
}
+static void
+set_max_gl_versions(struct intel_screen *screen)
+{
+ __DRIscreen *psp = screen->driScrnPriv;
+
+ switch (screen->devinfo->gen) {
+ case 7:
+ psp->max_gl_core_version = 33;
+ psp->max_gl_compat_version = 30;
+ psp->max_gl_es1_version = 11;
+ psp->max_gl_es2_version = 30;
+ break;
+ case 6:
+ psp->max_gl_core_version = 31;
+ psp->max_gl_compat_version = 30;
+ psp->max_gl_es1_version = 11;
+ psp->max_gl_es2_version = 30;
+ break;
+ case 5:
+ case 4:
+ psp->max_gl_core_version = 0;
+ psp->max_gl_compat_version = 21;
+ psp->max_gl_es1_version = 11;
+ psp->max_gl_es2_version = 20;
+ break;
+ default:
+ assert(!"unrecognized intel_screen::gen");
+ break;
+ }
+}
/**
- * This is the bootstrap function for the driver. libGL supplies all of the
- * requisite information about the system, and the driver initializes itself.
- * This routine also fills in the linked list pointed to by \c driver_modes
- * with the \c __GLcontextModes that the driver can support for windows or
- * pbuffers.
- *
- * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
- * failure.
+ * This is the driver specific part of the createNewScreen entry point.
+ * Called when using DRI2.
+ *
+ * \return the struct gl_config supported by this driver
*/
-PUBLIC
-void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
- const __GLcontextModes * modes,
- const __DRIversion * ddx_version,
- const __DRIversion * dri_version,
- const __DRIversion * drm_version,
- const __DRIframebuffer * frame_buffer,
- drmAddress pSAREA, int fd,
- int internal_api_version,
- const __DRIinterfaceMethods * interface,
- __GLcontextModes ** driver_modes )
-
-{
- __DRIscreenPrivate *psp;
- static const __DRIversion ddx_expected = { 1, 6, 0 };
- static const __DRIversion dri_expected = { 4, 0, 0 };
- static const __DRIversion drm_expected = { 1, 3, 0 };
-
- dri_interface = interface;
-
- if ( ! driCheckDriDdxDrmVersions2( "i915",
- dri_version, & dri_expected,
- ddx_version, & ddx_expected,
- drm_version, & drm_expected ) ) {
- return NULL;
+static const
+__DRIconfig **intelInitScreen2(__DRIscreen *psp)
+{
+ struct intel_screen *intelScreen;
+
+ if (psp->image.loader) {
+ } else if (psp->dri2.loader->base.version <= 2 ||
+ psp->dri2.loader->getBuffersWithFormat == NULL) {
+ fprintf(stderr,
+ "\nERROR! DRI2 loader with getBuffersWithFormat() "
+ "support required\n");
+ return false;
}
- psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
- ddx_version, dri_version, drm_version,
- frame_buffer, pSAREA, fd,
- internal_api_version, &intelAPI);
- if ( psp != NULL ) {
- I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
- *driver_modes = intelFillInModes( dri_priv->cpp * 8,
- (dri_priv->cpp == 2) ? 16 : 24,
- (dri_priv->cpp == 2) ? 0 : 8,
- GL_TRUE );
- /* Calling driInitExtensions here, with a NULL context pointer, does not actually
- * enable the extensions. It just makes sure that all the dispatch offsets for all
- * the extensions that *might* be enables are known. This is needed because the
- * dispatch offsets need to be known when _mesa_context_create is called, but we can't
- * enable the extensions until we have a context pointer.
- *
- * Hello chicken. Hello egg. How are you two today?
- */
- intelInitExtensions(NULL, GL_FALSE);
+ /* Allocate the private area */
+ intelScreen = calloc(1, sizeof *intelScreen);
+ if (!intelScreen) {
+ fprintf(stderr, "\nERROR! Allocating private area failed\n");
+ return false;
}
+ /* parse information in __driConfigOptions */
+ driParseOptionInfo(&intelScreen->optionCache, brw_config_options.xml);
+
+ intelScreen->driScrnPriv = psp;
+ psp->driverPrivate = (void *) intelScreen;
+
+ if (!intel_init_bufmgr(intelScreen))
+ return false;
+
+ intelScreen->deviceID = drm_intel_bufmgr_gem_get_devid(intelScreen->bufmgr);
+ intelScreen->devinfo = brw_get_device_info(intelScreen->deviceID);
+
+ intelScreen->hw_must_use_separate_stencil = intelScreen->devinfo->gen >= 7;
+
+ intelScreen->hw_has_swizzling = intel_detect_swizzling(intelScreen);
+
+ set_max_gl_versions(intelScreen);
+
+ psp->extensions = intelScreenExtensions;
+
+ return (const __DRIconfig**) intel_screen_make_configs(psp);
+}
+
+struct intel_buffer {
+ __DRIbuffer base;
+ struct intel_region *region;
+};
+
+static __DRIbuffer *
+intelAllocateBuffer(__DRIscreen *screen,
+ unsigned attachment, unsigned format,
+ int width, int height)
+{
+ struct intel_buffer *intelBuffer;
+ struct intel_screen *intelScreen = screen->driverPrivate;
+
+ assert(attachment == __DRI_BUFFER_FRONT_LEFT ||
+ attachment == __DRI_BUFFER_BACK_LEFT);
+
+ intelBuffer = calloc(1, sizeof *intelBuffer);
+ if (intelBuffer == NULL)
+ return NULL;
+
+ /* The front and back buffers are color buffers, which are X tiled. */
+ intelBuffer->region = intel_region_alloc(intelScreen,
+ I915_TILING_X,
+ format / 8,
+ width,
+ height,
+ true);
+
+ if (intelBuffer->region == NULL) {
+ free(intelBuffer);
+ return NULL;
+ }
+
+ intel_region_flink(intelBuffer->region, &intelBuffer->base.name);
+
+ intelBuffer->base.attachment = attachment;
+ intelBuffer->base.cpp = intelBuffer->region->cpp;
+ intelBuffer->base.pitch = intelBuffer->region->pitch;
+
+ return &intelBuffer->base;
+}
+
+static void
+intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
+{
+ struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer;
+
+ intel_region_release(&intelBuffer->region);
+ free(intelBuffer);
+}
+
+static const struct __DriverAPIRec brw_driver_api = {
+ .InitScreen = intelInitScreen2,
+ .DestroyScreen = intelDestroyScreen,
+ .CreateContext = brwCreateContext,
+ .DestroyContext = intelDestroyContext,
+ .CreateBuffer = intelCreateBuffer,
+ .DestroyBuffer = intelDestroyBuffer,
+ .MakeCurrent = intelMakeCurrent,
+ .UnbindContext = intelUnbindContext,
+ .AllocateBuffer = intelAllocateBuffer,
+ .ReleaseBuffer = intelReleaseBuffer
+};
+
+static const struct __DRIDriverVtableExtensionRec brw_vtable = {
+ .base = { __DRI_DRIVER_VTABLE, 1 },
+ .vtable = &brw_driver_api,
+};
+
+static const __DRIextension *brw_driver_extensions[] = {
+ &driCoreExtension.base,
+ &driImageDriverExtension.base,
+ &driDRI2Extension.base,
+ &brw_vtable.base,
+ &brw_config_options.base,
+ NULL
+};
+
+PUBLIC const __DRIextension **__driDriverGetExtensions_i965(void)
+{
+ globalDriverAPI = &brw_driver_api;
- return (void *) psp;
+ return brw_driver_extensions;
}