summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/drm/nouveau/nouveau_screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/drm/nouveau/nouveau_screen.c')
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_screen.c310
1 files changed, 310 insertions, 0 deletions
diff --git a/src/gallium/winsys/drm/nouveau/nouveau_screen.c b/src/gallium/winsys/drm/nouveau/nouveau_screen.c
new file mode 100644
index 0000000000..df1fe7e69b
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_screen.c
@@ -0,0 +1,310 @@
+#include "utils.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+#include "pipe/p_context.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_cb_fbo.h"
+
+#include "nouveau_context.h"
+#include "nouveau_drm.h"
+#include "nouveau_dri.h"
+#include "nouveau_local.h"
+#include "nouveau_screen.h"
+#include "nouveau_swapbuffers.h"
+
+#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 11
+#error nouveau_drm.h version does not match expected version
+#endif
+
+/* Extension stuff, enabling of extensions handled by Gallium's GL state
+ * tracker. But, we still need to define the entry points we want.
+ */
+#define need_GL_ARB_fragment_program
+#define need_GL_ARB_multisample
+#define need_GL_ARB_occlusion_query
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_shader_objects
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_vertex_shader
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_EXT_compiled_vertex_array
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_secondary_color
+#define need_GL_EXT_framebuffer_object
+#define need_GL_VERSION_2_0
+#define need_GL_VERSION_2_1
+#include "extension_helper.h"
+
+const struct dri_extension card_extensions[] =
+{
+ { "GL_ARB_multisample", GL_ARB_multisample_functions },
+ { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
+ { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
+ { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+ { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions },
+ { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions },
+ { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
+ { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions },
+ { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
+ { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
+ { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
+ { NULL, 0 }
+};
+
+PUBLIC const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+DRI_CONF_END;
+static const GLuint __driNConfigOptions = 0;
+
+extern const struct dri_extension common_extensions[];
+extern const struct dri_extension nv40_extensions[];
+
+static GLboolean
+nouveau_screen_create(__DRIscreenPrivate *driScrnPriv)
+{
+ struct nouveau_dri *nv_dri = driScrnPriv->pDevPriv;
+ struct nouveau_screen *nv_screen;
+ int ret;
+
+ if (driScrnPriv->devPrivSize != sizeof(struct nouveau_dri)) {
+ NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n");
+ return GL_FALSE;
+ }
+
+ nv_screen = CALLOC_STRUCT(nouveau_screen);
+ if (!nv_screen)
+ return GL_FALSE;
+ nv_screen->driScrnPriv = driScrnPriv;
+ driScrnPriv->private = (void *)nv_screen;
+
+ driParseOptionInfo(&nv_screen->option_cache,
+ __driConfigOptions, __driNConfigOptions);
+
+ if ((ret = nouveau_device_open_existing(&nv_screen->device, 0,
+ driScrnPriv->fd, 0))) {
+ NOUVEAU_ERR("Failed opening nouveau device: %d\n", ret);
+ return GL_FALSE;
+ }
+
+ nv_screen->front_offset = nv_dri->front_offset;
+ nv_screen->front_pitch = nv_dri->front_pitch * (nv_dri->bpp / 8);
+ nv_screen->front_cpp = nv_dri->bpp / 8;
+ nv_screen->front_height = nv_dri->height;
+
+ return GL_TRUE;
+}
+
+static void
+nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv)
+{
+ struct nouveau_screen *nv_screen = driScrnPriv->private;
+
+ driScrnPriv->private = NULL;
+ FREE(nv_screen);
+}
+
+static GLboolean
+nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ const __GLcontextModes *glVis, GLboolean pixmapBuffer)
+{
+ struct nouveau_framebuffer *nvfb;
+ enum pipe_format colour, depth, stencil;
+
+ if (pixmapBuffer)
+ return GL_FALSE;
+
+ nvfb = CALLOC_STRUCT(nouveau_framebuffer);
+ if (!nvfb)
+ return GL_FALSE;
+
+ if (glVis->redBits == 5)
+ colour = PIPE_FORMAT_R5G6B5_UNORM;
+ else
+ colour = PIPE_FORMAT_A8R8G8B8_UNORM;
+
+ if (glVis->depthBits == 16)
+ depth = PIPE_FORMAT_Z16_UNORM;
+ else if (glVis->depthBits == 24)
+ depth = PIPE_FORMAT_Z24S8_UNORM;
+ else
+ depth = PIPE_FORMAT_NONE;
+
+ if (glVis->stencilBits == 8)
+ stencil = PIPE_FORMAT_Z24S8_UNORM;
+ else
+ stencil = PIPE_FORMAT_NONE;
+
+ nvfb->stfb = st_create_framebuffer(glVis, colour, depth, stencil,
+ driDrawPriv->w, driDrawPriv->h,
+ (void*)nvfb);
+ if (!nvfb->stfb) {
+ free(nvfb);
+ return GL_FALSE;
+ }
+
+ driDrawPriv->driverPrivate = (void *)nvfb;
+ return GL_TRUE;
+}
+
+static void
+nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv)
+{
+ struct nouveau_framebuffer *nvfb;
+
+ nvfb = (struct nouveau_framebuffer *)driDrawPriv->driverPrivate;
+ st_unreference_framebuffer(&nvfb->stfb);
+ free(nvfb);
+}
+
+static struct __DriverAPIRec
+nouveau_api = {
+ .InitDriver = nouveau_screen_create,
+ .DestroyScreen = nouveau_screen_destroy,
+ .CreateContext = nouveau_context_create,
+ .DestroyContext = nouveau_context_destroy,
+ .CreateBuffer = nouveau_create_buffer,
+ .DestroyBuffer = nouveau_destroy_buffer,
+ .SwapBuffers = nouveau_swap_buffers,
+ .MakeCurrent = nouveau_context_bind,
+ .UnbindContext = nouveau_context_unbind,
+ .GetSwapInfo = NULL,
+ .GetMSC = NULL,
+ .WaitForMSC = NULL,
+ .WaitForSBC = NULL,
+ .SwapBuffersMSC = NULL,
+ .CopySubBuffer = nouveau_copy_sub_buffer,
+ .setTexOffset = NULL
+};
+
+static __GLcontextModes *
+nouveau_fill_in_modes(unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer)
+{
+ __GLcontextModes * modes;
+ __GLcontextModes * m;
+ unsigned num_modes;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ int i;
+
+ static const struct {
+ GLenum format;
+ GLenum type;
+ } fb_format_array[] = {
+ { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 },
+ { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
+ { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
+ };
+
+ /* 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
+ };
+
+ uint8_t depth_bits_array[4] = { 0, 16, 24, 24 };
+ uint8_t stencil_bits_array[4] = { 0, 0, 0, 8 };
+ uint8_t msaa_samples_array[1] = { 0 };
+
+ depth_buffer_factor = 4;
+ back_buffer_factor = (have_back_buffer) ? 3 : 1;
+
+ num_modes = ((pixel_bits==16) ? 1 : 2) *
+ depth_buffer_factor * back_buffer_factor * 4;
+ modes = (*dri_interface->createContextModes)(num_modes,
+ sizeof(__GLcontextModes));
+ m = modes;
+
+ for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
+ if (!driFillInModes(&m, fb_format_array[i].format,
+ fb_format_array[i].type,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1,
+ GLX_TRUE_COLOR)) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+
+ if (!driFillInModes(&m, fb_format_array[i].format,
+ fb_format_array[i].type,
+ depth_bits_array,
+ stencil_bits_array,
+ depth_buffer_factor,
+ back_buffer_modes,
+ back_buffer_factor,
+ msaa_samples_array, 1,
+ GLX_DIRECT_COLOR)) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+ }
+
+ return modes;
+}
+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,
+ void * pSAREA, int fd, int internal_api_version,
+ const __DRIinterfaceMethods * interface,
+ __GLcontextModes ** driver_modes)
+{
+ __DRIscreenPrivate *psp;
+ static const __DRIversion ddx_expected =
+ { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected =
+ { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
+ struct nouveau_dri *nv_dri = NULL;
+
+ dri_interface = interface;
+
+ if (!driCheckDriDdxDrmVersions2("nouveau",
+ dri_version, &dri_expected,
+ ddx_version, &ddx_expected,
+ drm_version, &drm_expected)) {
+ return NULL;
+ }
+
+ if (drm_expected.patch != drm_version->patch) {
+ fprintf(stderr, "Incompatible DRM patch level.\n"
+ "Expected: %d\n" "Current : %d\n",
+ drm_expected.patch, drm_version->patch);
+ return NULL;
+ }
+
+ psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
+ ddx_version, dri_version, drm_version,
+ frame_buffer, pSAREA, fd,
+ internal_api_version,
+ &nouveau_api);
+ if (psp == NULL)
+ return NULL;
+ nv_dri = psp->pDevPriv;
+
+ *driver_modes = nouveau_fill_in_modes(nv_dri->bpp,
+ (nv_dri->bpp == 16) ? 16 : 24,
+ (nv_dri->bpp == 16) ? 0 : 8,
+ 1);
+
+ driInitExtensions(NULL, card_extensions, GL_FALSE);
+
+ return (void *)psp;
+}
+