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
34static uint32_t
35radeon_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
64static 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 */
74static 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
95static 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
110Bool
111radeon_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 */
181struct radeon_buffer *
182radeon_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#ifdef GBM_BO_USE_LINEAR
215	if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
216	     info->shadow_primary) ||
217	    (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED)
218	    bo_use |= GBM_BO_USE_LINEAR;
219#endif
220
221	bo->bo.gbm = gbm_bo_create(info->gbm, width, height, gbm_format, bo_use);
222	if (!bo->bo.gbm) {
223	    free(bo);
224	    return NULL;
225	}
226
227	bo->flags |= RADEON_BO_FLAGS_GBM;
228
229	if (new_pitch)
230	    *new_pitch = gbm_bo_get_stride(bo->bo.gbm);
231
232	return bo;
233    }
234#endif
235
236    if (usage_hint) {
237	if (info->allowColorTiling) {
238	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
239		tiling |= RADEON_TILING_MACRO;
240	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
241                tiling |= RADEON_TILING_MICRO;
242	}
243	if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
244		tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
245
246	if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
247	     info->shadow_primary) ||
248	    (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) {
249		tiling = 0;
250		domain = RADEON_GEM_DOMAIN_GTT;
251	}
252    }
253
254    /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
255     * correctly because samplers automatically switch to macrolinear. */
256    if (info->ChipFamily >= CHIP_FAMILY_R300 &&
257        info->ChipFamily <= CHIP_FAMILY_RS740 &&
258        (tiling & RADEON_TILING_MACRO) &&
259        !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
260                           info->ChipFamily >= CHIP_FAMILY_RV350)) {
261        tiling &= ~RADEON_TILING_MACRO;
262    }
263
264    heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
265    pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
266    base_align = drmmode_get_base_align(pScrn, cpp, tiling);
267    size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
268
269    if (width && info->surf_man) {
270	if (!radeon_surface_initialize(info, &surface, width, height, cpp,
271				       tiling, usage_hint))
272	    return NULL;
273
274	size = surface.bo_size;
275	base_align = surface.bo_alignment;
276	pitch = surface.level[0].pitch_bytes;
277	tiling = 0;
278	switch (surface.level[0].mode) {
279	case RADEON_SURF_MODE_2D:
280	    tiling |= RADEON_TILING_MACRO;
281	    tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
282	    tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
283	    tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
284	    if (surface.tile_split)
285		tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
286	    if (surface.flags & RADEON_SURF_SBUFFER)
287		tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
288	    break;
289	case RADEON_SURF_MODE_1D:
290	    tiling |= RADEON_TILING_MICRO;
291	    break;
292	default:
293	    break;
294	}
295
296	if (new_surface)
297	    *new_surface = surface;
298    }
299
300    if (tiling)
301	flags |= RADEON_GEM_NO_CPU_ACCESS;
302
303    bo = calloc(1, sizeof(struct radeon_buffer));
304    if (!bo)
305	return NULL;
306
307    bo->ref_count = 1;
308    bo->bo.radeon = radeon_bo_open(info->bufmgr, 0, size, base_align,
309				   domain, flags);
310
311    if (bo->bo.radeon && tiling && radeon_bo_set_tiling(bo->bo.radeon, tiling, pitch) == 0)
312	*new_tiling = tiling;
313
314    *new_pitch = pitch;
315    return bo;
316}
317
318
319/* Flush and wait for the BO to become idle */
320void
321radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo)
322{
323    RADEONInfoPtr info = RADEONPTR(scrn);
324
325    if (info->use_glamor) {
326	radeon_glamor_finish(scrn);
327	return;
328    }
329
330    radeon_cs_flush_indirect(scrn);
331    radeon_bo_wait(bo->bo.radeon);
332}
333
334
335/* Clear the pixmap contents to black */
336void
337radeon_pixmap_clear(PixmapPtr pixmap)
338{
339    ScreenPtr screen = pixmap->drawable.pScreen;
340    RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen));
341    GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen);
342    Bool force = info->accel_state->force;
343    xRectangle rect;
344
345    info->accel_state->force = TRUE;
346    ValidateGC(&pixmap->drawable, gc);
347    rect.x = 0;
348    rect.y = 0;
349    rect.width = pixmap->drawable.width;
350    rect.height = pixmap->drawable.height;
351    gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect);
352    FreeScratchGC(gc);
353    info->accel_state->force = force;
354}
355
356/* Get GEM handle for the pixmap */
357Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle)
358{
359    struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap);
360#ifdef USE_GLAMOR
361    ScreenPtr screen = pixmap->drawable.pScreen;
362    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
363    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
364    RADEONInfoPtr info = RADEONPTR(scrn);
365#endif
366
367    if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) {
368	*handle = bo->bo.radeon->handle;
369	return TRUE;
370    }
371
372#ifdef USE_GLAMOR
373    if (info->use_glamor) {
374	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
375	CARD16 stride;
376	CARD32 size;
377	int fd, r;
378
379	if (!priv) {
380	    priv = calloc(1, sizeof(*priv));
381	    radeon_set_pixmap_private(pixmap, priv);
382	}
383
384	if (priv->handle_valid) {
385	    *handle = priv->handle;
386	    return TRUE;
387	}
388
389	fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
390	if (fd < 0)
391	    return FALSE;
392
393	r = drmPrimeFDToHandle(pRADEONEnt->fd, fd, &priv->handle);
394	close(fd);
395	if (r == 0) {
396	    struct drm_radeon_gem_set_tiling args = { .handle = priv->handle };
397
398	    priv->handle_valid = TRUE;
399	    *handle = priv->handle;
400
401	    if (drmCommandWriteRead(pRADEONEnt->fd,
402				    DRM_RADEON_GEM_GET_TILING, &args,
403				    sizeof(args)) == 0)
404		priv->tiling_flags = args.tiling_flags;
405
406	    return TRUE;
407	}
408    }
409#endif
410
411    return FALSE;
412}
413
414uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix)
415{
416#ifdef USE_GLAMOR
417    RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
418
419    if (info->use_glamor) {
420	struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix);
421
422	if (!priv || (!priv->bo && !priv->handle_valid)) {
423	    uint32_t handle;
424
425	    radeon_get_pixmap_handle(pPix, &handle);
426	    priv = radeon_get_pixmap_private(pPix);
427	}
428
429	return priv ? priv->tiling_flags : 0;
430    } else
431#endif
432    {
433	struct radeon_exa_pixmap_priv *driver_priv;
434	driver_priv = exaGetPixmapDriverPrivate(pPix);
435	return driver_priv ? driver_priv->tiling_flags : 0;
436    }
437}
438
439
440Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p)
441{
442    int handle;
443
444    if (radeon_gem_prime_share_bo(bo, &handle) != 0)
445	return FALSE;
446
447    *handle_p = (void *)(long)handle;
448    return TRUE;
449}
450
451Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
452				      struct radeon_surface *surface)
453{
454    ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen);
455    RADEONInfoPtr info = RADEONPTR(pScrn);
456    struct radeon_buffer *bo;
457    int ihandle = (int)(long)fd_handle;
458    uint32_t size = ppix->devKind * ppix->drawable.height;
459    Bool ret = FALSE;
460
461    if (ihandle == -1)
462	return radeon_set_pixmap_bo(ppix, NULL);
463
464    bo = (struct radeon_buffer *)calloc(1, sizeof(struct radeon_buffer));
465    if (!bo)
466	goto error;
467
468#ifdef USE_GLAMOR
469    if (info->use_glamor) {
470	struct gbm_import_fd_data data;
471	uint32_t bo_use = GBM_BO_USE_RENDERING;
472
473	data.format = radeon_get_gbm_format(ppix->drawable.depth,
474					    ppix->drawable.bitsPerPixel);
475	if (data.format == ~0U)
476	    goto error;
477
478	bo->ref_count = 1;
479
480	data.fd = ihandle;
481	data.width = ppix->drawable.width;
482	data.height = ppix->drawable.height;
483	data.stride = ppix->devKind;
484
485	if (ppix->drawable.bitsPerPixel == pScrn->bitsPerPixel)
486	    bo_use |= GBM_BO_USE_SCANOUT;
487
488	bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD, &data, bo_use);
489	if (!bo->bo.gbm)
490	    goto error;
491
492	bo->flags |= RADEON_BO_FLAGS_GBM;
493
494	if (!radeon_glamor_create_textured_pixmap(ppix, bo)) {
495	    radeon_buffer_unref(&bo);
496	    return FALSE;
497	}
498
499	ret = radeon_set_pixmap_bo(ppix, bo);
500	/* radeon_set_pixmap_bo increments ref_count if it succeeds */
501	radeon_buffer_unref(&bo);
502	return ret;
503    }
504#endif
505
506    bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size);
507    if (!bo->bo.radeon)
508        goto error;
509
510    bo->ref_count = 1;
511    ret = radeon_set_pixmap_bo(ppix, bo);
512    if (!ret)
513	goto error;
514
515    if (surface) {
516	struct radeon_exa_pixmap_priv *driver_priv;
517	uint32_t tiling_flags;
518
519	driver_priv = exaGetPixmapDriverPrivate(ppix);
520	tiling_flags = driver_priv->tiling_flags;
521
522	if (!radeon_surface_initialize(info, surface, ppix->drawable.width,
523				       ppix->drawable.height,
524				       ppix->drawable.bitsPerPixel / 8,
525				       tiling_flags, 0)) {
526	    ret = FALSE;
527	    goto error;
528	}
529
530	/* we have to post hack the surface to reflect the actual size
531	   of the shared pixmap */
532	surface->level[0].pitch_bytes = ppix->devKind;
533	surface->level[0].nblk_x = ppix->devKind / surface->bpe;
534    }
535
536 error:
537    close(ihandle);
538    /* we have a reference from the alloc and one from set pixmap bo,
539       drop one */
540    radeon_buffer_unref(&bo);
541    return ret;
542}
543