1 /*
2  * Copyright 2012  Advanced Micro Devices, Inc.
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, sublicense,
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 shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 
27 #include "radeon.h"
28 #include "radeon_glamor.h"
29 #include "radeon_bo_gem.h"
30 
31 
32 #ifdef USE_GLAMOR
33 
34 static uint32_t
radeon_get_gbm_format(int depth,int bitsPerPixel)35 radeon_get_gbm_format(int depth, int bitsPerPixel)
36 {
37     switch (depth) {
38 #ifdef GBM_FORMAT_R8
39     case 8:
40 	return GBM_FORMAT_R8;
41 #endif
42     case 15:
43 	return GBM_FORMAT_ARGB1555;
44     case 16:
45 	return GBM_FORMAT_RGB565;
46     case 32:
47 	return GBM_FORMAT_ARGB8888;
48     case 30:
49 	return GBM_FORMAT_XRGB2101010;
50     case 24:
51 	if (bitsPerPixel == 32)
52 	    return GBM_FORMAT_XRGB8888;
53 	/* fall through */
54     default:
55 	ErrorF("%s: Unsupported depth/bpp %d/%d\n", __func__, depth,
56 	       bitsPerPixel);
57 	return ~0U;
58     }
59 }
60 
61 #endif /* USE_GLAMOR */
62 
63 
64 static const unsigned MicroBlockTable[5][3][2] = {
65     /*linear  tiled   square-tiled */
66     {{32, 1}, {8, 4}, {0, 0}}, /*   8 bits per pixel */
67     {{16, 1}, {8, 2}, {4, 4}}, /*  16 bits per pixel */
68     {{ 8, 1}, {4, 2}, {0, 0}}, /*  32 bits per pixel */
69     {{ 4, 1}, {0, 0}, {2, 2}}, /*  64 bits per pixel */
70     {{ 2, 1}, {0, 0}, {0, 0}}  /* 128 bits per pixel */
71 };
72 
73 /* Return true if macrotiling can be enabled */
RADEONMacroSwitch(int width,int height,int bpp,uint32_t flags,Bool rv350_mode)74 static Bool RADEONMacroSwitch(int width, int height, int bpp,
75                               uint32_t flags, Bool rv350_mode)
76 {
77     unsigned tilew, tileh, microtiled, logbpp;
78 
79     logbpp = RADEONLog2(bpp / 8);
80     if (logbpp > 4)
81         return 0;
82 
83     microtiled = !!(flags & RADEON_TILING_MICRO);
84     tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
85     tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
86 
87     /* See TX_FILTER1_n.MACRO_SWITCH. */
88     if (rv350_mode) {
89         return width >= tilew && height >= tileh;
90     } else {
91         return width > tilew && height > tileh;
92     }
93 }
94 
eg_tile_split_opp(unsigned tile_split)95 static unsigned eg_tile_split_opp(unsigned tile_split)
96 {
97     switch (tile_split) {
98         case 0:     tile_split = 64;    break;
99         case 1:     tile_split = 128;   break;
100         case 2:     tile_split = 256;   break;
101         case 3:     tile_split = 512;   break;
102         default:
103         case 4:     tile_split = 1024;  break;
104         case 5:     tile_split = 2048;  break;
105         case 6:     tile_split = 4096;  break;
106     }
107     return tile_split;
108 }
109 
110 Bool
radeon_surface_initialize(RADEONInfoPtr info,struct radeon_surface * surface,int width,int height,int cpp,uint32_t tiling_flags,int usage_hint)111 radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface,
112 			  int width, int height, int cpp, uint32_t tiling_flags,
113 			  int usage_hint)
114 {
115 	memset(surface, 0, sizeof(struct radeon_surface));
116 
117 	surface->npix_x = width;
118 	/* need to align height to 8 for old kernel */
119 	surface->npix_y = RADEON_ALIGN(height, 8);
120 	surface->npix_z = 1;
121 	surface->blk_w = 1;
122 	surface->blk_h = 1;
123 	surface->blk_d = 1;
124 	surface->array_size = 1;
125 	surface->last_level = 0;
126 	surface->bpe = cpp;
127 	surface->nsamples = 1;
128 	if (height < 128) {
129 	    /* disable 2d tiling for small surface to work around
130 	     * the fact that ddx align height to 8 pixel for old
131 	     * obscure reason i can't remember
132 	     */
133 	    tiling_flags &= ~RADEON_TILING_MACRO;
134 	}
135 
136 	surface->flags = RADEON_SURF_SCANOUT | RADEON_SURF_HAS_TILE_MODE_INDEX |
137 	    RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
138 
139 	if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
140 	    surface->flags |= RADEON_SURF_ZBUFFER;
141 	    surface->flags |= RADEON_SURF_SBUFFER;
142 	}
143 
144 	if ((tiling_flags & RADEON_TILING_MACRO)) {
145 	    surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
146 	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
147 	} else if ((tiling_flags & RADEON_TILING_MICRO)) {
148 	    surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
149 	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
150 	} else
151 	    surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
152 
153 	if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
154 	    surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) &
155 		RADEON_TILING_EG_BANKW_MASK;
156 	    surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) &
157 		RADEON_TILING_EG_BANKH_MASK;
158 	    surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) &
159 						    RADEON_TILING_EG_TILE_SPLIT_MASK);
160 	    if (surface->flags & RADEON_SURF_SBUFFER) {
161 		surface->stencil_tile_split =
162 		    (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) &
163 		    RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK;
164 	    }
165 	    surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) &
166 		RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
167 	}
168 
169 	if (radeon_surface_best(info->surf_man, surface))
170 	    return FALSE;
171 
172 	if (radeon_surface_init(info->surf_man, surface))
173 	    return FALSE;
174 
175 	return TRUE;
176 }
177 
178 /* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that
179  * can hold it.
180  */
181 struct radeon_buffer *
radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn,int width,int height,int depth,int usage_hint,int bitsPerPixel,int * new_pitch,struct radeon_surface * new_surface,uint32_t * new_tiling)182 radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
183 		       int usage_hint, int bitsPerPixel, int *new_pitch,
184 		       struct radeon_surface *new_surface, uint32_t *new_tiling)
185 {
186     RADEONInfoPtr info = RADEONPTR(pScrn);
187     int pitch, base_align;
188     uint32_t size, heighta;
189     int cpp = bitsPerPixel / 8;
190     uint32_t tiling = 0, flags = 0;
191     struct radeon_surface surface;
192     struct radeon_buffer *bo;
193     int domain = RADEON_GEM_DOMAIN_VRAM;
194 
195 #ifdef USE_GLAMOR
196     if (info->use_glamor &&
197 	!(usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
198 	  info->shadow_primary)) {
199 	uint32_t bo_use = GBM_BO_USE_RENDERING;
200 	uint32_t gbm_format = radeon_get_gbm_format(depth, bitsPerPixel);
201 
202 	if (gbm_format == ~0U)
203 	    return NULL;
204 
205 	bo = calloc(1, sizeof(struct radeon_buffer));
206 	if (!bo)
207 	    return NULL;
208 
209 	bo->ref_count = 1;
210 
211 	if (bitsPerPixel == pScrn->bitsPerPixel)
212 	    bo_use |= GBM_BO_USE_SCANOUT;
213 
214 	if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
215 	     info->shadow_primary) ||
216 	    (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED)
217 	    bo_use |= GBM_BO_USE_LINEAR;
218 
219 	bo->bo.gbm = gbm_bo_create(info->gbm, width, height, gbm_format, bo_use);
220 	if (!bo->bo.gbm) {
221 	    free(bo);
222 	    return NULL;
223 	}
224 
225 	bo->flags |= RADEON_BO_FLAGS_GBM;
226 
227 	if (new_pitch)
228 	    *new_pitch = gbm_bo_get_stride(bo->bo.gbm);
229 
230 	return bo;
231     }
232 #endif
233 
234     if (usage_hint) {
235 	if (info->allowColorTiling) {
236 	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
237 		tiling |= RADEON_TILING_MACRO;
238 	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
239                 tiling |= RADEON_TILING_MICRO;
240 	}
241 	if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
242 		tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
243 
244 	if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
245 	     info->shadow_primary) ||
246 	    (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) {
247 		tiling = 0;
248 		domain = RADEON_GEM_DOMAIN_GTT;
249 	}
250     }
251 
252     /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
253      * correctly because samplers automatically switch to macrolinear. */
254     if (info->ChipFamily >= CHIP_FAMILY_R300 &&
255         info->ChipFamily <= CHIP_FAMILY_RS740 &&
256         (tiling & RADEON_TILING_MACRO) &&
257         !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
258                            info->ChipFamily >= CHIP_FAMILY_RV350)) {
259         tiling &= ~RADEON_TILING_MACRO;
260     }
261 
262     heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
263     pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
264     base_align = drmmode_get_base_align(pScrn, cpp, tiling);
265     size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
266 
267     if (width && info->surf_man) {
268 	if (!radeon_surface_initialize(info, &surface, width, height, cpp,
269 				       tiling, usage_hint))
270 	    return NULL;
271 
272 	size = surface.bo_size;
273 	base_align = surface.bo_alignment;
274 	pitch = surface.level[0].pitch_bytes;
275 	tiling = 0;
276 	switch (surface.level[0].mode) {
277 	case RADEON_SURF_MODE_2D:
278 	    tiling |= RADEON_TILING_MACRO;
279 	    tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
280 	    tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
281 	    tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
282 	    if (surface.tile_split)
283 		tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
284 	    if (surface.flags & RADEON_SURF_SBUFFER)
285 		tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
286 	    break;
287 	case RADEON_SURF_MODE_1D:
288 	    tiling |= RADEON_TILING_MICRO;
289 	    break;
290 	default:
291 	    break;
292 	}
293 
294 	if (new_surface)
295 	    *new_surface = surface;
296     }
297 
298     if (tiling)
299 	flags |= RADEON_GEM_NO_CPU_ACCESS;
300 
301     bo = calloc(1, sizeof(struct radeon_buffer));
302     if (!bo)
303 	return NULL;
304 
305     bo->ref_count = 1;
306     bo->bo.radeon = radeon_bo_open(info->bufmgr, 0, size, base_align,
307 				   domain, flags);
308 
309     if (bo && tiling && radeon_bo_set_tiling(bo->bo.radeon, tiling, pitch) == 0)
310 	*new_tiling = tiling;
311 
312     *new_pitch = pitch;
313     return bo;
314 }
315 
316 
317 /* Flush and wait for the BO to become idle */
318 void
radeon_finish(ScrnInfoPtr scrn,struct radeon_buffer * bo)319 radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo)
320 {
321     RADEONInfoPtr info = RADEONPTR(scrn);
322 
323     if (info->use_glamor) {
324 	radeon_glamor_finish(scrn);
325 	return;
326     }
327 
328     radeon_cs_flush_indirect(scrn);
329     radeon_bo_wait(bo->bo.radeon);
330 }
331 
332 
333 /* Clear the pixmap contents to black */
334 void
radeon_pixmap_clear(PixmapPtr pixmap)335 radeon_pixmap_clear(PixmapPtr pixmap)
336 {
337     ScreenPtr screen = pixmap->drawable.pScreen;
338     RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen));
339     GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen);
340     Bool force = info->accel_state->force;
341     xRectangle rect;
342 
343     info->accel_state->force = TRUE;
344     ValidateGC(&pixmap->drawable, gc);
345     rect.x = 0;
346     rect.y = 0;
347     rect.width = pixmap->drawable.width;
348     rect.height = pixmap->drawable.height;
349     gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect);
350     FreeScratchGC(gc);
351     info->accel_state->force = force;
352 }
353 
354 /* Get GEM handle for the pixmap */
radeon_get_pixmap_handle(PixmapPtr pixmap,uint32_t * handle)355 Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle)
356 {
357     struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap);
358 #ifdef USE_GLAMOR
359     ScreenPtr screen = pixmap->drawable.pScreen;
360     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
361     RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
362     RADEONInfoPtr info = RADEONPTR(scrn);
363 #endif
364 
365     if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) {
366 	*handle = bo->bo.radeon->handle;
367 	return TRUE;
368     }
369 
370 #ifdef USE_GLAMOR
371     if (info->use_glamor) {
372 	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
373 	CARD16 stride;
374 	CARD32 size;
375 	int fd, r;
376 
377 	if (!priv) {
378 	    priv = calloc(1, sizeof(*priv));
379 	    radeon_set_pixmap_private(pixmap, priv);
380 	}
381 
382 	if (priv->handle_valid) {
383 	    *handle = priv->handle;
384 	    return TRUE;
385 	}
386 
387 	fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
388 	if (fd < 0)
389 	    return FALSE;
390 
391 	r = drmPrimeFDToHandle(pRADEONEnt->fd, fd, &priv->handle);
392 	close(fd);
393 	if (r == 0) {
394 	    struct drm_radeon_gem_set_tiling args = { .handle = priv->handle };
395 
396 	    priv->handle_valid = TRUE;
397 	    *handle = priv->handle;
398 
399 	    if (drmCommandWriteRead(pRADEONEnt->fd,
400 				    DRM_RADEON_GEM_GET_TILING, &args,
401 				    sizeof(args)) == 0)
402 		priv->tiling_flags = args.tiling_flags;
403 
404 	    return TRUE;
405 	}
406     }
407 #endif
408 
409     return FALSE;
410 }
411 
radeon_get_pixmap_tiling_flags(PixmapPtr pPix)412 uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix)
413 {
414 #ifdef USE_GLAMOR
415     RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
416 
417     if (info->use_glamor) {
418 	struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix);
419 
420 	if (!priv || (!priv->bo && !priv->handle_valid)) {
421 	    uint32_t handle;
422 
423 	    radeon_get_pixmap_handle(pPix, &handle);
424 	    priv = radeon_get_pixmap_private(pPix);
425 	}
426 
427 	return priv ? priv->tiling_flags : 0;
428     } else
429 #endif
430     {
431 	struct radeon_exa_pixmap_priv *driver_priv;
432 	driver_priv = exaGetPixmapDriverPrivate(pPix);
433 	return driver_priv ? driver_priv->tiling_flags : 0;
434     }
435 }
436 
437 
radeon_share_pixmap_backing(struct radeon_bo * bo,void ** handle_p)438 Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p)
439 {
440     int handle;
441 
442     if (radeon_gem_prime_share_bo(bo, &handle) != 0)
443 	return FALSE;
444 
445     *handle_p = (void *)(long)handle;
446     return TRUE;
447 }
448 
radeon_set_shared_pixmap_backing(PixmapPtr ppix,void * fd_handle,struct radeon_surface * surface)449 Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
450 				      struct radeon_surface *surface)
451 {
452     ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen);
453     RADEONInfoPtr info = RADEONPTR(pScrn);
454     struct radeon_buffer *bo;
455     int ihandle = (int)(long)fd_handle;
456     uint32_t size = ppix->devKind * ppix->drawable.height;
457     Bool ret = FALSE;
458 
459     if (ihandle == -1)
460 	return radeon_set_pixmap_bo(ppix, NULL);
461 
462     bo = (struct radeon_buffer *)calloc(1, sizeof(struct radeon_buffer));
463     if (!bo)
464 	goto error;
465 
466 #ifdef USE_GLAMOR
467     if (info->use_glamor) {
468 	struct gbm_import_fd_data data;
469 	uint32_t bo_use = GBM_BO_USE_RENDERING;
470 
471 	data.format = radeon_get_gbm_format(ppix->drawable.depth,
472 					    ppix->drawable.bitsPerPixel);
473 	if (data.format == ~0U)
474 	    goto error;
475 
476 	bo->ref_count = 1;
477 
478 	data.fd = ihandle;
479 	data.width = ppix->drawable.width;
480 	data.height = ppix->drawable.height;
481 	data.stride = ppix->devKind;
482 
483 	if (ppix->drawable.bitsPerPixel == pScrn->bitsPerPixel)
484 	    bo_use |= GBM_BO_USE_SCANOUT;
485 
486 	bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD, &data, bo_use);
487 	if (!bo->bo.gbm)
488 	    goto error;
489 
490 	bo->flags |= RADEON_BO_FLAGS_GBM;
491 
492 	if (!radeon_glamor_create_textured_pixmap(ppix, bo)) {
493 	    radeon_buffer_unref(&bo);
494 	    return FALSE;
495 	}
496 
497 	ret = radeon_set_pixmap_bo(ppix, bo);
498 	/* radeon_set_pixmap_bo increments ref_count if it succeeds */
499 	radeon_buffer_unref(&bo);
500 	return ret;
501     }
502 #endif
503 
504     bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size);
505     if (!bo)
506         goto error;
507 
508     bo->ref_count = 1;
509     ret = radeon_set_pixmap_bo(ppix, bo);
510     if (!ret)
511 	goto error;
512 
513     if (surface) {
514 	struct radeon_exa_pixmap_priv *driver_priv;
515 	uint32_t tiling_flags;
516 
517 	driver_priv = exaGetPixmapDriverPrivate(ppix);
518 	tiling_flags = driver_priv->tiling_flags;
519 
520 	if (!radeon_surface_initialize(info, surface, ppix->drawable.width,
521 				       ppix->drawable.height,
522 				       ppix->drawable.bitsPerPixel / 8,
523 				       tiling_flags, 0)) {
524 	    ret = FALSE;
525 	    goto error;
526 	}
527 
528 	/* we have to post hack the surface to reflect the actual size
529 	   of the shared pixmap */
530 	surface->level[0].pitch_bytes = ppix->devKind;
531 	surface->level[0].nblk_x = ppix->devKind / surface->bpe;
532     }
533 
534  error:
535     close(ihandle);
536     /* we have a reference from the alloc and one from set pixmap bo,
537        drop one */
538     radeon_buffer_unref(&bo);
539     return ret;
540 }
541