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/fbobject.h" 37 #include "main/renderbuffer.h" 38 #include "swrast/s_renderbuffer.h" 39 40 static const __DRIextension *nouveau_screen_extensions[]; 41 42 static void 43 nouveau_destroy_screen(__DRIscreen *dri_screen); 44 45 static const __DRIconfig ** 46 nouveau_get_configs(void) 47 { 48 __DRIconfig **configs = NULL; 49 int i; 50 51 const uint8_t depth_bits[] = { 0, 16, 24, 24 }; 52 const uint8_t stencil_bits[] = { 0, 0, 0, 8 }; 53 const uint8_t msaa_samples[] = { 0 }; 54 55 const struct { 56 GLenum format; 57 GLenum type; 58 } fb_formats[] = { 59 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 }, 60 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, 61 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, 62 }; 63 64 const GLenum back_buffer_modes[] = { 65 GLX_NONE, GLX_SWAP_UNDEFINED_OML 66 }; 67 68 for (i = 0; i < Elements(fb_formats); i++) { 69 __DRIconfig **config; 70 71 config = driCreateConfigs(fb_formats[i].format, 72 fb_formats[i].type, 73 depth_bits, stencil_bits, 74 Elements(depth_bits), 75 back_buffer_modes, 76 Elements(back_buffer_modes), 77 msaa_samples, 78 Elements(msaa_samples), 79 GL_TRUE); 80 assert(config); 81 82 configs = driConcatConfigs(configs, config); 83 } 84 85 return (const __DRIconfig **)configs; 86 } 87 88 static const __DRIconfig ** 89 nouveau_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; 131 fail: 132 nouveau_destroy_screen(dri_screen); 133 return NULL; 134 135 } 136 137 static void 138 nouveau_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 151 static GLboolean 152 nouveau_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 210 static void 211 nouveau_destroy_buffer(__DRIdrawable *drawable) 212 { 213 _mesa_reference_framebuffer( 214 (struct gl_framebuffer **)&drawable->driverPrivate, NULL); 215 } 216 217 static void 218 nouveau_drawable_flush(__DRIdrawable *draw) 219 { 220 } 221 222 static const struct __DRI2flushExtensionRec nouveau_flush_extension = { 223 { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, 224 nouveau_drawable_flush, 225 dri2InvalidateDrawable, 226 }; 227 228 static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = { 229 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, 230 NULL, 231 nouveau_set_texbuffer, 232 }; 233 234 static const __DRIextension *nouveau_screen_extensions[] = { 235 &nouveau_flush_extension.base, 236 &nouveau_texbuffer_extension.base, 237 &dri2ConfigQueryExtension.base, 238 NULL 239 }; 240 241 const 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. */ 253 PUBLIC const __DRIextension *__driDriverExtensions[] = { 254 &driCoreExtension.base, 255 &driDRI2Extension.base, 256 NULL 257 }; 258