via_memmgr.c revision 90b17f1b
1/* 2 * Copyright 2003 Red Hat, Inc. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sub license, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27#include <sys/mman.h> 28 29#include "xf86.h" 30#include "xf86_OSproc.h" 31#include "xf86fbman.h" 32 33#ifdef HAVE_DRI 34#include "xf86drm.h" 35#endif 36 37#include "via_driver.h" 38#ifdef HAVE_DRI 39#include "via_drm.h" 40#endif 41 42/* 43 * Isolate the wonders of X memory allocation and DRI memory allocation 44 * and 4.3 or 4.4 differences in one abstraction. 45 * 46 * The pool code indicates who provided the memory: 47 * 0 - nobody 48 * 1 - xf86 linear 49 * 2 - DRM 50 */ 51int 52viaOffScreenLinear(struct buffer_object *obj, ScrnInfoPtr pScrn, 53 unsigned long size) 54{ 55 int depth = pScrn->bitsPerPixel >> 3; 56 FBLinearPtr linear; 57 58 linear = xf86AllocateOffscreenLinear(pScrn->pScreen, 59 (size + depth - 1) / depth, 60 32, NULL, NULL, NULL); 61 if (!linear) 62 return BadAlloc; 63 obj->offset = linear->offset * depth; 64 obj->handle = (unsigned long) linear; 65 obj->domain = TTM_PL_FLAG_VRAM; 66 obj->size = size; 67 return Success; 68} 69 70struct buffer_object * 71drm_bo_alloc_surface(ScrnInfoPtr pScrn, unsigned int width, unsigned int height, 72 int format, unsigned int alignment, int domain) 73{ 74 struct buffer_object *obj = NULL; 75 int pitch; 76 77 switch (format) { 78 case DRM_FORMAT_C8: 79 pitch = width; 80 break; 81 82 case DRM_FORMAT_XRGB1555: 83 case DRM_FORMAT_RGB565: 84 pitch = width * 2; 85 break; 86 87 case DRM_FORMAT_RGB888: 88 pitch = width * 3; 89 break; 90 91 case DRM_FORMAT_XRGB2101010: 92 case DRM_FORMAT_XRGB8888: 93 pitch = width * 4; 94 break; 95 } 96 97 pitch = ALIGN_TO(pitch, alignment); 98 obj = drm_bo_alloc(pScrn, pitch * height, alignment, domain); 99 if (!obj->pitch) 100 obj->pitch = pitch; 101 return obj; 102} 103 104struct buffer_object * 105drm_bo_alloc(ScrnInfoPtr pScrn, unsigned int size, unsigned int alignment, int domain) 106{ 107 struct buffer_object *obj = NULL; 108 VIAPtr pVia = VIAPTR(pScrn); 109 int ret = 0; 110 111 obj = xnfcalloc(1, sizeof(*obj)); 112 if (obj) { 113 switch (domain) { 114 case TTM_PL_FLAG_TT: 115 case TTM_PL_FLAG_VRAM: 116 if (pVia->directRenderingType == DRI_NONE) { 117 if (Success != viaOffScreenLinear(obj, pScrn, size)) { 118 ErrorF("Linear memory allocation failed\n"); 119 ret = -ENOMEM; 120 } else 121 DEBUG(ErrorF("%lu bytes of Linear memory allocated at %lx, handle %lu\n", obj->size, obj->offset, obj->handle)); 122#ifdef HAVE_DRI 123 } else if (pVia->directRenderingType == DRI_1) { 124 drm_via_mem_t drm; 125 126 size = ALIGN_TO(size, alignment); 127 drm.context = DRIGetContext(pScrn->pScreen); 128 drm.size = size; 129 drm.type = (domain == TTM_PL_FLAG_TT ? VIA_MEM_AGP : VIA_MEM_VIDEO); 130 ret = drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_ALLOCMEM, 131 &drm, sizeof(drm_via_mem_t)); 132 if (!ret && (size == drm.size)) { 133 if (domain == TTM_PL_FLAG_VRAM) 134 drm.offset -= pVia->FBFreeStart; 135 obj->offset = ALIGN_TO(drm.offset, alignment); 136 obj->handle = drm.index; 137 obj->domain = domain; 138 obj->size = drm.size; 139 DEBUG(ErrorF("%lu bytes of DRI memory allocated at %lx, handle %lu\n", 140 obj->size, obj->offset, obj->handle)); 141 } 142 } else if (pVia->directRenderingType == DRI_2) { 143 struct drm_via_gem_create args; 144 145 /* Some day this will be moved to libdrm. */ 146 args.domains = domain; 147 args.alignment = alignment; 148 args.pitch = 0; 149 args.size = size; 150 ret = drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_GEM_CREATE, 151 &args, sizeof(struct drm_via_gem_create)); 152 if (!ret) { 153 /* Okay the X server expects to know the offset because 154 * of non-KMS. Once we have KMS working the offset 155 * will not be valid. */ 156 obj->map_offset = args.map_handle; 157 obj->offset = args.offset; 158 obj->handle = args.handle; 159 obj->pitch = args.pitch; 160 obj->size = args.size; 161 obj->domain = domain; 162 DEBUG(ErrorF("%lu bytes of DRI2 memory allocated at %lx, handle %lu\n", 163 obj->size, obj->offset, obj->handle)); 164 } 165#endif 166 } 167 break; 168 169 case TTM_PL_FLAG_SYSTEM: 170 default: 171 ret = -ENXIO; 172 break; 173 } 174 175 if (ret) { 176 DEBUG(ErrorF("DRM memory allocation failed %d\n", ret)); 177 free(obj); 178 obj = NULL; 179 }; 180 } 181 return obj; 182} 183 184void* 185drm_bo_map(ScrnInfoPtr pScrn, struct buffer_object *obj) 186{ 187 VIAPtr pVia = VIAPTR(pScrn); 188 189 if (pVia->directRenderingType == DRI_2) { 190 obj->ptr = mmap(0, obj->size, PROT_READ | PROT_WRITE, 191 MAP_SHARED, pVia->drmmode.fd, obj->map_offset); 192 if (obj->ptr == MAP_FAILED) { 193 DEBUG(ErrorF("mmap failed with error %d\n", -errno)); 194 obj->ptr = NULL; 195 } 196 } else { 197 switch (obj->domain) { 198#ifdef HAVE_DRI 199 case TTM_PL_FLAG_TT: 200 obj->ptr = (pVia->agpMappedAddr + obj->offset); 201 break; 202#endif 203 case TTM_PL_FLAG_VRAM: 204 obj->ptr = (pVia->FBBase + obj->offset); 205 break; 206 default: 207 obj->ptr = NULL; 208 break; 209 } 210 } 211 return obj->ptr; 212} 213 214void 215drm_bo_unmap(ScrnInfoPtr pScrn, struct buffer_object *obj) 216{ 217 VIAPtr pVia = VIAPTR(pScrn); 218 219 if (pVia->directRenderingType == DRI_2) 220 munmap(obj->ptr, obj->size); 221 obj->ptr = NULL; 222} 223 224void 225drm_bo_free(ScrnInfoPtr pScrn, struct buffer_object *obj) 226{ 227 VIAPtr pVia = VIAPTR(pScrn); 228 229 if (obj) { 230 DEBUG(ErrorF("Freed %lu (pool %d)\n", obj->offset, obj->domain)); 231 switch (obj->domain) { 232 case TTM_PL_FLAG_VRAM: 233 case TTM_PL_FLAG_TT: 234 if (pVia->directRenderingType == DRI_NONE) { 235 FBLinearPtr linear = (FBLinearPtr) obj->handle; 236 237 xf86FreeOffscreenLinear(linear); 238#ifdef HAVE_DRI 239 } else if (pVia->directRenderingType == DRI_1) { 240 drm_via_mem_t drm; 241 242 drm.index = obj->handle; 243 if (drmCommandWrite(pVia->drmmode.fd, DRM_VIA_FREEMEM, 244 &drm, sizeof(drm_via_mem_t)) < 0) 245 ErrorF("DRM failed to free for handle %lu.\n", obj->handle); 246 } else if (pVia->directRenderingType == DRI_2) { 247 struct drm_gem_close close; 248 249 close.handle = obj->handle; 250 if (drmIoctl(pVia->drmmode.fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) 251 ErrorF("DRM failed to free for handle %lu.\n", obj->handle); 252#endif 253 } 254 break; 255 256 default: 257 break; 258 } 259 free(obj); 260 } 261} 262 263Bool 264drm_bo_manager_init(ScrnInfoPtr pScrn) 265{ 266 VIAPtr pVia = VIAPTR(pScrn); 267 Bool ret = TRUE; 268 269 if (pVia->directRenderingType == DRI_2) 270 return ret; 271 ret = ums_create(pScrn); 272#ifdef HAVE_DRI 273 if (pVia->directRenderingType == DRI_1) 274 ret = VIADRIKernelInit(pScrn); 275#endif 276 return ret; 277} 278