diff options
Diffstat (limited to 'src/gallium/winsys/drm/nouveau/nouveau_screen.c')
-rw-r--r-- | src/gallium/winsys/drm/nouveau/nouveau_screen.c | 265 |
1 files changed, 265 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 00000000000..c6d0c535887 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/nouveau_screen.c @@ -0,0 +1,265 @@ +#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_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 __DRIconfig ** +nouveau_fill_in_modes(__DRIscreenPrivate *psp, + unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer) +{ + __DRIconfig **configs; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, + }; + + uint8_t depth_bits_array[3]; + uint8_t stencil_bits_array[3]; + uint8_t msaa_samples_array[1]; + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + depth_bits_array[2] = depth_bits; + + /* 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. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 0; + if (depth_bits == 24) + stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; + stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; + + msaa_samples_array[0] = 0; + + depth_buffer_factor = + ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; + back_buffer_factor = (have_back_buffer) ? 3 : 1; + + 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; + } + + configs = driCreateConfigs(fb_format, fb_type, + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + back_buffer_factor, msaa_samples_array, 1); + if (configs == NULL) { + fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__); + return NULL; + } + + return configs; +} + +static const __DRIconfig ** +nouveau_screen_create(__DRIscreenPrivate *psp) +{ + struct nouveau_dri *nv_dri = psp->pDevPriv; + struct nouveau_screen *nv_screen; + 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 }; + int ret; + + if (!driCheckDriDdxDrmVersions2("nouveau", + &psp->dri_version, &dri_expected, + &psp->ddx_version, &ddx_expected, + &psp->drm_version, &drm_expected)) { + return NULL; + } + + if (drm_expected.patch != psp->drm_version.patch) { + fprintf(stderr, "Incompatible DRM patch level.\n" + "Expected: %d\n" "Current : %d\n", + drm_expected.patch, psp->drm_version.patch); + return NULL; + } + + driInitExtensions(NULL, card_extensions, GL_FALSE); + + if (psp->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 = psp; + psp->private = (void *)nv_screen; + + driParseOptionInfo(&nv_screen->option_cache, + __driConfigOptions, __driNConfigOptions); + + if ((ret = nouveau_device_open_existing(&nv_screen->device, 0, + psp->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 (const __DRIconfig **) + nouveau_fill_in_modes(psp, nv_dri->bpp, + (nv_dri->bpp == 16) ? 16 : 24, + (nv_dri->bpp == 16) ? 0 : 8, 1); +} + +static void +nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv) +{ + struct nouveau_screen *nv_screen = driScrnPriv->private; + + driScrnPriv->private = NULL; + FREE(nv_screen); +} + +const struct __DriverAPIRec +driDriverAPI = { + .InitScreen = 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, + .CopySubBuffer = nouveau_copy_sub_buffer, + + .InitScreen2 = NULL, /* one day, I promise! */ +}; + |