nouveau_screen.c revision 2e47d01c9e5325906cf3bb979279599991c6328e
1/* 2 * Copyright (C) 2009 Francisco Jerez. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 */ 26 27#include "nouveau_driver.h" 28#include "nouveau_context.h" 29#include "nouveau_fbo.h" 30#include "nouveau_texture.h" 31#include "nv04_driver.h" 32#include "nv10_driver.h" 33#include "nv20_driver.h" 34 35#include "main/framebuffer.h" 36#include "main/renderbuffer.h" 37#include "swrast/s_renderbuffer.h" 38 39static const __DRIextension *nouveau_screen_extensions[]; 40 41static void 42nouveau_destroy_screen(__DRIscreen *dri_screen); 43 44static const __DRIconfig ** 45nouveau_get_configs(void) 46{ 47 __DRIconfig **configs = NULL; 48 int i; 49 50 const uint8_t depth_bits[] = { 0, 16, 24, 24 }; 51 const uint8_t stencil_bits[] = { 0, 0, 0, 8 }; 52 const uint8_t msaa_samples[] = { 0 }; 53 54 const struct { 55 GLenum format; 56 GLenum type; 57 } fb_formats[] = { 58 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 }, 59 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, 60 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, 61 }; 62 63 const GLenum back_buffer_modes[] = { 64 GLX_NONE, GLX_SWAP_UNDEFINED_OML 65 }; 66 67 for (i = 0; i < Elements(fb_formats); i++) { 68 __DRIconfig **config; 69 70 config = driCreateConfigs(fb_formats[i].format, 71 fb_formats[i].type, 72 depth_bits, stencil_bits, 73 Elements(depth_bits), 74 back_buffer_modes, 75 Elements(back_buffer_modes), 76 msaa_samples, 77 Elements(msaa_samples), 78 GL_TRUE); 79 assert(config); 80 81 configs = configs ? driConcatConfigs(configs, config) 82 : config; 83 } 84 85 return (const __DRIconfig **)configs; 86} 87 88static const __DRIconfig ** 89nouveau_init_screen2(__DRIscreen *dri_screen) 90{ 91 const __DRIconfig **configs; 92 struct nouveau_screen *screen; 93 int ret; 94 95 /* Allocate the screen. */ 96 screen = CALLOC_STRUCT(nouveau_screen); 97 if (!screen) 98 return NULL; 99 100 dri_screen->driverPrivate = screen; 101 dri_screen->extensions = nouveau_screen_extensions; 102 screen->dri_screen = dri_screen; 103 104 /* Open the DRM device. */ 105 ret = nouveau_device_wrap(dri_screen->fd, 0, &screen->device); 106 if (ret) { 107 nouveau_error("Error opening the DRM device.\n"); 108 goto fail; 109 } 110 111 /* Choose the card specific function pointers. */ 112 switch (screen->device->chipset & 0xf0) { 113 case 0x00: 114 screen->driver = &nv04_driver; 115 break; 116 case 0x10: 117 screen->driver = &nv10_driver; 118 break; 119 case 0x20: 120 screen->driver = &nv20_driver; 121 break; 122 default: 123 assert(0); 124 } 125 126 configs = nouveau_get_configs(); 127 if (!configs) 128 goto fail; 129 130 return configs; 131fail: 132 nouveau_destroy_screen(dri_screen); 133 return NULL; 134 135} 136 137static void 138nouveau_destroy_screen(__DRIscreen *dri_screen) 139{ 140 struct nouveau_screen *screen = dri_screen->driverPrivate; 141 142 if (!screen) 143 return; 144 145 nouveau_device_del(&screen->device); 146 147 FREE(screen); 148 dri_screen->driverPrivate = NULL; 149} 150 151static GLboolean 152nouveau_create_buffer(__DRIscreen *dri_screen, 153 __DRIdrawable *drawable, 154 const struct gl_config *visual, 155 GLboolean is_pixmap) 156{ 157 struct gl_renderbuffer *rb; 158 struct gl_framebuffer *fb; 159 GLenum color_format; 160 161 if (is_pixmap) 162 return GL_FALSE; /* not implemented */ 163 164 if (visual->redBits == 5) 165 color_format = GL_RGB5; 166 else if (visual->alphaBits == 0) 167 color_format = GL_RGB8; 168 else 169 color_format = GL_RGBA8; 170 171 fb = nouveau_framebuffer_dri_new(visual); 172 if (!fb) 173 return GL_FALSE; 174 175 /* Front buffer. */ 176 rb = nouveau_renderbuffer_dri_new(color_format, drawable); 177 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb); 178 179 /* Back buffer */ 180 if (visual->doubleBufferMode) { 181 rb = nouveau_renderbuffer_dri_new(color_format, drawable); 182 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb); 183 } 184 185 /* Depth/stencil buffer. */ 186 if (visual->depthBits == 24 && visual->stencilBits == 8) { 187 rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable); 188 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 189 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); 190 191 } else if (visual->depthBits == 24) { 192 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable); 193 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 194 195 } else if (visual->depthBits == 16) { 196 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable); 197 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 198 } 199 200 /* Software renderbuffers. */ 201 _swrast_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE, 202 visual->accumRedBits > 0, 203 GL_FALSE, GL_FALSE); 204 205 drawable->driverPrivate = fb; 206 207 return GL_TRUE; 208} 209 210static void 211nouveau_destroy_buffer(__DRIdrawable *drawable) 212{ 213 _mesa_reference_framebuffer( 214 (struct gl_framebuffer **)&drawable->driverPrivate, NULL); 215} 216 217static void 218nouveau_drawable_flush(__DRIdrawable *draw) 219{ 220} 221 222static const struct __DRI2flushExtensionRec nouveau_flush_extension = { 223 { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, 224 nouveau_drawable_flush, 225 dri2InvalidateDrawable, 226}; 227 228static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = { 229 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, 230 NULL, 231 nouveau_set_texbuffer, 232}; 233 234static const __DRIextension *nouveau_screen_extensions[] = { 235 &nouveau_flush_extension.base, 236 &nouveau_texbuffer_extension.base, 237 &dri2ConfigQueryExtension.base, 238 NULL 239}; 240 241const struct __DriverAPIRec driDriverAPI = { 242 .InitScreen = nouveau_init_screen2, 243 .DestroyScreen = nouveau_destroy_screen, 244 .CreateBuffer = nouveau_create_buffer, 245 .DestroyBuffer = nouveau_destroy_buffer, 246 .CreateContext = nouveau_context_create, 247 .DestroyContext = nouveau_context_destroy, 248 .MakeCurrent = nouveau_context_make_current, 249 .UnbindContext = nouveau_context_unbind, 250}; 251 252/* This is the table of extensions that the loader will dlsym() for. */ 253PUBLIC const __DRIextension *__driDriverExtensions[] = { 254 &driCoreExtension.base, 255 &driDRI2Extension.base, 256 NULL 257}; 258