diff options
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r-- | src/drmmode_display.c | 136 |
1 files changed, 119 insertions, 17 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 02968d51..89ac6d7d 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -49,12 +49,16 @@ #include <X11/extensions/dpms.h> #endif -static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen, +static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, int width, int height, int depth, int bpp, - int pitch, struct radeon_bo *bo) + int pitch, int tiling, + struct radeon_bo *bo) { + RADEONInfoPtr info = RADEONPTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; PixmapPtr pixmap; + struct radeon_surface *surface; pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0); if (!pixmap) @@ -67,6 +71,37 @@ static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen, exaMoveInPixmap(pixmap); radeon_set_pixmap_bo(pixmap, bo); + surface = radeon_get_pixmap_surface(pixmap); + if (surface) { + memset(surface, 0, sizeof(struct radeon_surface)); + surface->npix_x = width; + surface->npix_y = height; + surface->npix_z = 1; + surface->blk_w = 1; + surface->blk_h = 1; + surface->blk_d = 1; + surface->array_size = 1; + surface->last_level = 0; + surface->bpe = bpp / 8; + surface->nsamples = 1; + surface->flags = RADEON_SURF_SCANOUT; + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); + if (tiling & RADEON_TILING_MICRO) { + surface->flags = RADEON_SURF_CLR(surface->flags, MODE); + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + } + if (tiling & RADEON_TILING_MACRO) { + surface->flags = RADEON_SURF_CLR(surface->flags, MODE); + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); + } + if (radeon_surface_best(info->surf_man, surface)) { + return FALSE; + } + if (radeon_surface_init(info->surf_man, surface)) { + return FALSE; + } + } return pixmap; } @@ -159,7 +194,6 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc; - ScreenPtr pScreen = pScrn->pScreen; PixmapPtr pixmap; struct radeon_bo *bo; drmModeFBPtr fbcon; @@ -185,9 +219,9 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, return NULL; } - pixmap = drmmode_create_bo_pixmap(pScreen, fbcon->width, fbcon->height, + pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, fbcon->depth, fbcon->bpp, - fbcon->pitch, bo); + fbcon->pitch, 0, bo); if (!pixmap) return NULL; @@ -225,9 +259,13 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) return; if (info->allowColorTiling) { - if (info->ChipFamily >= CHIP_FAMILY_R600) - tiling_flags |= RADEON_TILING_MICRO; - else + if (info->ChipFamily >= CHIP_FAMILY_R600) { + if (info->allowColorTiling2D) { + tiling_flags |= RADEON_TILING_MACRO; + } else { + tiling_flags |= RADEON_TILING_MICRO; + } + } else tiling_flags |= RADEON_TILING_MACRO; } @@ -235,10 +273,10 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * info->CurrentLayout.pixel_bytes; - dst = drmmode_create_bo_pixmap(pScreen, pScrn->virtualX, + dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX, pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, pitch, - info->front_bo); + tiling_flags, info->front_bo); if (!dst) goto out_free_src; @@ -292,6 +330,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * info->CurrentLayout.pixel_bytes; height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)); + if (info->ChipFamily >= CHIP_FAMILY_R600) { + pitch = info->front_surface.level[0].pitch_bytes; + } if (drmmode->fb_id == 0) { ret = drmModeAddFB(drmmode->fd, @@ -503,12 +544,12 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp; - rotate_pixmap = drmmode_create_bo_pixmap(pScrn->pScreen, + rotate_pixmap = drmmode_create_bo_pixmap(pScrn, width, height, pScrn->depth, pScrn->bitsPerPixel, rotate_pitch, - drmmode_crtc->rotate_bo); + 0, drmmode_crtc->rotate_bo); if (rotate_pixmap == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't allocate shadow pixmap for rotated CRTC\n"); @@ -1206,7 +1247,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) int screen_size; int cpp = info->CurrentLayout.pixel_bytes; struct radeon_bo *front_bo; - uint32_t tiling_flags = 0; + struct radeon_surface surface; + struct radeon_surface *psurface; + uint32_t tiling_flags = 0, base_align; PixmapPtr ppix = screen->GetScreenPixmap(screen); void *fb_shadow; @@ -1220,15 +1263,69 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) radeon_bo_wait(front_bo); if (info->allowColorTiling) { - if (info->ChipFamily >= CHIP_FAMILY_R600) - tiling_flags |= RADEON_TILING_MICRO; - else + if (info->ChipFamily >= CHIP_FAMILY_R600) { + if (info->allowColorTiling2D) { + tiling_flags |= RADEON_TILING_MACRO; + } else { + tiling_flags |= RADEON_TILING_MICRO; + } + } else tiling_flags |= RADEON_TILING_MACRO; } pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp; height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags)); screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE); + base_align = 4096; + if (info->ChipFamily >= CHIP_FAMILY_R600) { + memset(&surface, 0, sizeof(struct radeon_surface)); + surface.npix_x = width; + surface.npix_y = height; + surface.npix_z = 1; + surface.blk_w = 1; + surface.blk_h = 1; + surface.blk_d = 1; + surface.array_size = 1; + surface.last_level = 0; + surface.bpe = cpp; + surface.nsamples = 1; + surface.flags = RADEON_SURF_SCANOUT; + surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); + surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); + if (tiling_flags & RADEON_TILING_MICRO) { + surface.flags = RADEON_SURF_CLR(surface.flags, MODE); + surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + } + if (tiling_flags & RADEON_TILING_MACRO) { + surface.flags = RADEON_SURF_CLR(surface.flags, MODE); + surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); + } + if (radeon_surface_best(info->surf_man, &surface)) { + return FALSE; + } + if (radeon_surface_init(info->surf_man, &surface)) { + return FALSE; + } + screen_size = surface.bo_size; + base_align = surface.bo_alignment; + pitch = surface.level[0].pitch_bytes; + tiling_flags = 0; + switch (surface.level[0].mode) { + case RADEON_SURF_MODE_2D: + tiling_flags |= RADEON_TILING_MACRO; + tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; + tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; + tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; + tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; + break; + case RADEON_SURF_MODE_1D: + tiling_flags |= RADEON_TILING_MICRO; + break; + default: + break; + } + info->front_surface = surface; + } xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d stride %d\n", @@ -1244,7 +1341,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) scrn->virtualY = height; scrn->displayWidth = pitch / cpp; - info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, 0, RADEON_GEM_DOMAIN_VRAM, 0); + info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0); if (!info->front_bo) goto fail; @@ -1270,6 +1367,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) if (!info->r600_shadow_fb) { radeon_set_pixmap_bo(ppix, info->front_bo); + psurface = radeon_get_pixmap_surface(ppix); + *psurface = info->front_surface; screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, NULL); } else { @@ -1671,6 +1770,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * info->CurrentLayout.pixel_bytes; height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags)); + if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { + pitch = info->front_surface.level[0].pitch_bytes; + } /* * Create a new handle for the back buffer |