diff --git a/configure.ac b/configure.ac index b8c18a6..a7e954d 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,14 @@ if test "$DRI" = yes; then if test "$have_damage_h" = yes; then AC_DEFINE(DAMAGE,1,[Use Damage extension]) fi + + save_CFLAGS="$CFLAGS" + CFLAGS="$XORG_CFLAGS $DRI_CFLAGS" + AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include +#include ]) + if test "x$DRM_MODE" = xyes; then + AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting]) + fi fi save_CFLAGS="$CFLAGS" diff --git a/src/Makefile.am b/src/Makefile.am index 97c686b..b8d09bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -90,12 +90,13 @@ radeon_drv_ladir = @moduledir@/drivers radeon_drv_la_SOURCES = \ radeon_accel.c radeon_cursor.c radeon_dga.c \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ - radeon_vip.c radeon_misc.c radeon_probe.c \ + radeon_vip.c radeon_misc.c radeon_probe.c radeon_memory.c \ legacy_crtc.c legacy_output.c \ radeon_textured_video.c \ radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \ $(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \ - $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c + $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c \ + drmmode_display.c radeon_bufmgr_exa.c radeon_bufmgr_gem.c radeon_dri_bufmgr.c if XMODES radeon_drv_la_SOURCES += \ @@ -160,4 +161,6 @@ EXTRA_DIST = \ radeon_pci_device_match_gen.h \ pcidb/ati_pciids.csv \ pcidb/parse_pci_ids.pl \ - radeon_atombios.h + radeon_atombios.h \ + drmmode_display.h \ + radeon_dri_bufmgr.h diff --git a/src/drmmode_display.c b/src/drmmode_display.c new file mode 100644 index 0000000..3073c15 --- /dev/null +++ b/src/drmmode_display.c @@ -0,0 +1,685 @@ +/* + * Copyright © 2007 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Dave Airlie + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef XF86DRM_MODE +#include "radeon.h" +#include "sarea.h" + +static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height); + +static Bool +drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + Bool ret; + + ErrorF("resize called %d %d\n", width, height); + ret = drmmode_resize_fb(scrn, drmmode, width, height); + scrn->virtualX = width; + scrn->virtualY = height; + return TRUE; +} + +static void +drmmode_ConvertFromKMode(ScrnInfoPtr scrn, + struct drm_mode_modeinfo *kmode, + DisplayModePtr mode) +{ + memset(mode, 0, sizeof(DisplayModeRec)); + mode->status = MODE_OK; + + mode->Clock = kmode->clock; + + mode->HDisplay = kmode->hdisplay; + mode->HSyncStart = kmode->hsync_start; + mode->HSyncEnd = kmode->hsync_end; + mode->HTotal = kmode->htotal; + mode->HSkew = kmode->hskew; + + mode->VDisplay = kmode->vdisplay; + mode->VSyncStart = kmode->vsync_start; + mode->VSyncEnd = kmode->vsync_end; + mode->VTotal = kmode->vtotal; + mode->VScan = kmode->vscan; + + mode->Flags = kmode->flags; //& FLAG_BITS; + mode->name = strdup(kmode->name); + + if (kmode->type & DRM_MODE_TYPE_DRIVER) + mode->type = M_T_DRIVER; + if (kmode->type & DRM_MODE_TYPE_PREFERRED) + mode->type |= M_T_PREFERRED; + xf86SetModeCrtc (mode, scrn->adjustFlags); +} + +static void +drmmode_ConvertToKMode(ScrnInfoPtr scrn, + struct drm_mode_modeinfo *kmode, + DisplayModePtr mode) +{ + memset(kmode, 0, sizeof(*kmode)); + + kmode->clock = mode->Clock; + kmode->hdisplay = mode->HDisplay; + kmode->hsync_start = mode->HSyncStart; + kmode->hsync_end = mode->HSyncEnd; + kmode->htotal = mode->HTotal; + kmode->hskew = mode->HSkew; + + kmode->vdisplay = mode->VDisplay; + kmode->vsync_start = mode->VSyncStart; + kmode->vsync_end = mode->VSyncEnd; + kmode->vtotal = mode->VTotal; + kmode->vscan = mode->VScan; + + kmode->flags = mode->Flags; //& FLAG_BITS; + if (mode->name) + strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); + kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; + +} + +static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { + drmmode_xf86crtc_resize +}; + +static void +drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode) +{ + +} + +static Bool +drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, + Rotation rotation, int x, int y) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + int saved_x, saved_y; + Rotation saved_rotation; + DisplayModeRec saved_mode; + uint32_t *output_ids; + int output_count = 0; + Bool ret = TRUE; + int i; + int fb_id; + struct drm_mode_modeinfo kmode; + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; + + output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output); + if (!output_ids) { + ret = FALSE; + goto done; + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + drmmode_output_private_ptr drmmode_output; + + if (output->crtc != crtc) + continue; + + drmmode_output = output->driver_private; + output_ids[output_count] = drmmode_output->mode_output->connector_id; + output_count++; + } + + if (!xf86CrtcRotate(crtc, mode, rotation)) { + goto done; + } + + drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); + + + fb_id = drmmode->fb_id; + if (drmmode_crtc->rotate_fb_id) + fb_id = drmmode_crtc->rotate_fb_id; + ErrorF("fb id is %d\n", fb_id); + drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + fb_id, x, y, output_ids, output_count, &kmode); + + if (crtc->scrn->pScreen) + xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen); + + +done: + if (!ret) { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + crtc->mode = saved_mode; + } + return ret; +} + +static void +drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) +{ + +} + +static void +drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); +} + +static void +drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + void *ptr; + + /* cursor should be mapped already */ + ptr = drmmode_crtc->cursor_map; + + memcpy (ptr, image, 64 * 64 * 4); + + return; +} + + +static void +drmmode_hide_cursor (xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64); + +} + +static void +drmmode_show_cursor (xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, drmmode_crtc->cursor_handle, 64, 64); +} + +static void * +drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + int size; + unsigned long rotate_pitch; + dri_bo *rotate_bo; + int ret; + rotate_pitch = crtc->scrn->displayWidth * drmmode->cpp; + size = rotate_pitch * height; + + rotate_bo = dri_bo_alloc(drmmode->bufmgr, "rotate", size, 0, 0); + if (rotate_bo == NULL) + return NULL; + + radeon_bufmgr_pin(rotate_bo); + dri_bo_map(rotate_bo, 1); + + ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, + crtc->scrn->bitsPerPixel, rotate_pitch, radeon_bufmgr_get_handle(rotate_bo), + &drmmode_crtc->rotate_fb_id); + if (ret) { + ErrorF("failed to add rotate fb\n"); + } + + drmmode_crtc->rotate_bo = rotate_bo; + return drmmode_crtc->rotate_bo->virtual; +} + +static PixmapPtr +drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + unsigned long rotate_pitch; + PixmapPtr rotate_pixmap; + + if (!data) + data = drmmode_crtc_shadow_allocate (crtc, width, height); + + rotate_pitch = pScrn->displayWidth * drmmode->cpp; + + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + rotate_pitch, + data); + + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + } + return rotate_pixmap; + +} + +static void +drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + if (rotate_pixmap) + FreeScratchPixmapHeader(rotate_pixmap); + + if (data) { + drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id); + drmmode_crtc->rotate_fb_id = 0; + dri_bo_unreference(drmmode_crtc->rotate_bo); + drmmode_crtc->rotate_bo = NULL; + } + +} + +static const xf86CrtcFuncsRec drmmode_crtc_funcs = { + .dpms = drmmode_crtc_dpms, + .set_mode_major = drmmode_set_mode_major, + .set_cursor_colors = drmmode_set_cursor_colors, + .set_cursor_position = drmmode_set_cursor_position, + .show_cursor = drmmode_show_cursor, + .hide_cursor = drmmode_hide_cursor, + .load_cursor_argb = drmmode_load_cursor_argb, + + .shadow_create = drmmode_crtc_shadow_create, + .shadow_allocate = drmmode_crtc_shadow_allocate, + .shadow_destroy = drmmode_crtc_shadow_destroy, +#if 0 + .gamma_set = i830_crtc_gamma_set, +#endif + .destroy = NULL, /* XXX */ +}; + + +static void +drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) +{ + xf86CrtcPtr crtc; + drmmode_crtc_private_ptr drmmode_crtc; + + crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); + if (crtc == NULL) + return; + + drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); + drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); + drmmode_crtc->drmmode = drmmode; + crtc->driver_private = drmmode_crtc; + + return; +} + +static xf86OutputStatus +drmmode_output_detect(xf86OutputPtr output) +{ + /* go to the hw and retrieve a new output struct */ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmmode_ptr drmmode = drmmode_output->drmmode; + xf86OutputStatus status; + drmModeFreeConnector(drmmode_output->mode_output); + + drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id); + + switch (drmmode_output->mode_output->connection) { + case DRM_MODE_CONNECTED: + status = XF86OutputStatusConnected; + break; + case DRM_MODE_DISCONNECTED: + status = XF86OutputStatusDisconnected; + break; + default: + case DRM_MODE_UNKNOWNCONNECTION: + status = XF86OutputStatusUnknown; + break; + } + return status; +} + +static Bool +drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) +{ + return MODE_OK; +} + +static DisplayModePtr +drmmode_output_get_modes(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + drmmode_ptr drmmode = drmmode_output->drmmode; + int i; + DisplayModePtr Modes = NULL, Mode; + drmModePropertyPtr props; + + /* look for an EDID property */ + for (i = 0; i < koutput->count_props; i++) { + props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + if (props && (props->flags & DRM_MODE_PROP_BLOB)) { + if (!strcmp(props->name, "EDID")) { + if (drmmode_output->edid_blob) + drmModeFreePropertyBlob(drmmode_output->edid_blob); + drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); + } + drmModeFreeProperty(props); + } + } + + if (drmmode_output->edid_blob) + xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data)); + else + xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL)); + + /* modes should already be available */ + for (i = 0; i < koutput->count_modes; i++) { + Mode = xnfalloc(sizeof(DisplayModeRec)); + + drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); + Modes = xf86ModesAdd(Modes, Mode); + + } + return Modes; +} + +static void +drmmode_output_destroy(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + + if (drmmode_output->edid_blob) + drmModeFreePropertyBlob(drmmode_output->edid_blob); + drmModeFreeConnector(drmmode_output->mode_output); + xfree(drmmode_output); + output->driver_private = NULL; +} + +static void +drmmode_output_dpms(xf86OutputPtr output, int mode) +{ + return; +} + +static const xf86OutputFuncsRec drmmode_output_funcs = { + .dpms = drmmode_output_dpms, +#if 0 + + .save = drmmode_crt_save, + .restore = drmmode_crt_restore, + .mode_fixup = drmmode_crt_mode_fixup, + .prepare = drmmode_output_prepare, + .mode_set = drmmode_crt_mode_set, + .commit = drmmode_output_commit, +#endif + .detect = drmmode_output_detect, + .mode_valid = drmmode_output_mode_valid, + + .get_modes = drmmode_output_get_modes, + .destroy = drmmode_output_destroy +}; + +static int subpixel_conv_table[7] = { 0, SubPixelUnknown, + SubPixelHorizontalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalRGB, + SubPixelVerticalBGR, + SubPixelNone }; + +const char *output_names[] = { "None", + "VGA", + "DVI", + "DVI", + "DVI", + "Composite", + "TV", + "LVDS", + "CTV", + "DIN", + "DP", + "HDMI", + "HDMI", +}; + + +static void +drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) +{ + xf86OutputPtr output; + drmModeConnectorPtr koutput; + drmModeEncoderPtr kencoder; + drmmode_output_private_ptr drmmode_output; + char name[32]; + + koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]); + if (!koutput) + return; + + kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]); + if (!kencoder) { + drmModeFreeConnector(koutput); + return; + } + + snprintf(name, 32, "%s%d", output_names[koutput->connector_type], koutput->connector_type_id); + + output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); + if (!output) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + + drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1); + if (!drmmode_output) { + xf86OutputDestroy(output); + drmModeFreeConnector(koutput); + drmModeFreeEncoder(kencoder); + return; + } + + drmmode_output->output_id = drmmode->mode_res->connectors[num]; + drmmode_output->mode_output = koutput; + drmmode_output->mode_encoder = kencoder; + drmmode_output->drmmode = drmmode; + output->mm_width = koutput->mmWidth; + output->mm_height = koutput->mmHeight; + + output->subpixel_order = subpixel_conv_table[koutput->subpixel]; + output->driver_private = drmmode_output; + + output->possible_crtcs = kencoder->possible_crtcs; + output->possible_clones = kencoder->possible_clones; + + return; +} + +Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp) +{ + xf86CrtcConfigPtr xf86_config; + int i; + Bool ret; + + /* Create a bus Id */ + /* Low level DRM open */ + ret = DRIOpenDRMMaster(pScrn, SAREA_MAX, busId, driver_name); + if (!ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] DRIGetVersion failed to open the DRM\n" + "[dri] Disabling DRI.\n"); + return FALSE; + } + + drmmode->fd = DRIMasterFD(pScrn); + + xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + drmmode->cpp = cpp; + drmmode->mode_res = drmModeGetResources(drmmode->fd); + if (!drmmode->mode_res) + return FALSE; + + xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height); + for (i = 0; i < drmmode->mode_res->count_crtcs; i++) + drmmode_crtc_init(pScrn, drmmode, i); + + for (i = 0; i < drmmode->mode_res->count_connectors; i++) + drmmode_output_init(pScrn, drmmode, i); + + xf86InitialConfiguration(pScrn, FALSE); + + return TRUE; +} + +Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, dri_bufmgr *bufmgr) +{ + drmmode->bufmgr = bufmgr; + return TRUE; +} + +void drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height, int pitch, uint32_t handle) +{ + int ret; + + ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, + scrn->bitsPerPixel, pitch, handle, + &drmmode->fb_id); + + if (ret) { + ErrorF("Failed to add fb\n"); + } + + drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id); + if (!drmmode->mode_fb) + return; + + + ErrorF("Add fb id %d %d %d\n", drmmode->fb_id, width, height); +} + +void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, void *ptr, uint32_t handle) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc = xf86_config->crtc[id]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + + drmmode_crtc->cursor_handle = handle; + drmmode_crtc->cursor_map = ptr; +} + +Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); + int i; + + if (pPixData == NULL) + return FALSE; + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + if (!drmmode_crtc->rotate_bo) + continue; + + if (drmmode_crtc->rotate_bo->virtual == pPixData) { + *bo = drmmode_crtc->rotate_bo; + return TRUE; + } + } + return FALSE; + +} + +static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height) +{ + uint32_t handle; + int pitch; + int ret; + + return FALSE; + + if (drmmode->mode_fb->width == width && drmmode->mode_fb->height == height) + return TRUE; + + if (!drmmode->create_new_fb) + return FALSE; + + handle = drmmode->create_new_fb(scrn, width, height, &pitch); + if (handle == 0) + return FALSE; + + ret = drmModeReplaceFB(drmmode->fd, drmmode->fb_id, + width, height, + scrn->depth, scrn->bitsPerPixel, pitch, + handle); + + if (ret) + return FALSE; + + drmModeFreeFB(drmmode->mode_fb); + drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id); + if (!drmmode->mode_fb) + return FALSE; + + return TRUE; +} + +void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; + + if (crtc && crtc->enabled) { + drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, + x, y); + } +} + +#endif diff --git a/src/drmmode_display.h b/src/drmmode_display.h new file mode 100644 index 0000000..691d62e --- /dev/null +++ b/src/drmmode_display.h @@ -0,0 +1,74 @@ +/* + * Copyright © 2007 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Dave Airlie + * + */ +#ifndef DRMMODE_DISPLAY_H +#define DRMMODE_DISPLAY_H + +#ifdef XF86DRM_MODE + +#include "xf86drmMode.h" + +#include "radeon_probe.h" +#include "radeon_bufmgr.h" + +typedef struct { + int fd; + int fb_id; + drmModeResPtr mode_res; + drmModeFBPtr mode_fb; + int cpp; + dri_bufmgr *bufmgr; + + uint32_t (*create_new_fb)(ScrnInfoPtr pScrn, int width, int height, int *pitch); +} drmmode_rec, *drmmode_ptr; + +typedef struct { + + drmmode_ptr drmmode; + drmModeCrtcPtr mode_crtc; + uint32_t cursor_handle; + void *cursor_map; + dri_bo *rotate_bo; + int rotate_fb_id; +} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; + +typedef struct { + drmmode_ptr drmmode; + int output_id; + drmModeConnectorPtr mode_output; + drmModeEncoderPtr mode_encoder; + drmModePropertyBlobPtr edid_blob; +} drmmode_output_private_rec, *drmmode_output_private_ptr; + + +extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp); +extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, dri_bufmgr *bufmgr); +extern void drmmode_set_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int width, int height, int pitch, uint32_t handle); +extern Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo); +extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, void *ptr, uint32_t handle); +void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags); +#endif +#endif diff --git a/src/radeon.h b/src/radeon.h index 2348e7c..aeea221 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -46,6 +46,8 @@ #include "compiler.h" #include "xf86fbman.h" +#include "drmmode_display.h" + /* PCI support */ #include "xf86Pci.h" @@ -84,6 +86,7 @@ #include "xf86Crtc.h" #include "X11/Xatom.h" +#include "radeon_bufmgr.h" /* Render support */ #ifdef RENDER #include "picturestr.h" @@ -403,6 +406,14 @@ typedef enum { typedef struct _atomBiosHandle *atomBiosHandlePtr; +#define RADEON_POOL_GART 0 +#define RADEON_POOL_VRAM 1 + +struct radeon_exa_pixmap_priv { + dri_bo *bo; + int flags; +}; + typedef struct { uint32_t pci_device_id; RADEONChipFamily chip_family; @@ -413,6 +424,25 @@ typedef struct { int singledac; } RADEONCardInfo; +#define RADEON_2D_EXA_COPY 1 +#define RADEON_2D_EXA_SOLID 2 + +struct radeon_2d_state { + int op; // + uint32_t dst_pitch_offset; + uint32_t src_pitch_offset; + uint32_t dp_gui_master_cntl; + uint32_t dp_cntl; + uint32_t dp_write_mask; + uint32_t dp_brush_frgd_clr; + uint32_t dp_brush_bkgd_clr; + uint32_t dp_src_frgd_clr; + uint32_t dp_src_bkgd_clr; + uint32_t default_sc_bottom_right; + dri_bo *dst_bo; + dri_bo *src_bo; +}; + typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; @@ -612,13 +642,13 @@ typedef struct { drm_handle_t ringHandle; /* Handle from drmAddMap */ drmSize ringMapSize; /* Size of map */ int ringSize; /* Size of ring (in MB) */ - drmAddress ring; /* Map */ + // drmAddress ring; /* Map */ int ringSizeLog2QW; unsigned long ringReadOffset; /* Offset into GART space */ drm_handle_t ringReadPtrHandle; /* Handle from drmAddMap */ drmSize ringReadMapSize; /* Size of map */ - drmAddress ringReadPtr; /* Map */ + // drmAddress ringReadPtr; /* Map */ /* CP vertex/indirect buffer data */ unsigned long bufStart; /* Offset into GART space */ @@ -641,6 +671,9 @@ typedef struct { drmBufPtr indirectBuffer; int indirectStart; + drmBuf ib_gem_fake; + void *ib_ptr; + /* DRI screen private data */ int fbX; int fbY; @@ -798,6 +831,45 @@ typedef struct { int num_gb_pipes; Bool has_tcl; + + Bool new_cs; // new command submission routine + struct radeon_2d_state state_2d; + void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB + Bool cs_used_depth; + Bool drm_mm; // the drm memory manager exists and is initialised + struct { + uint64_t vram_start; + uint64_t vram_size; + uint64_t gart_start; + uint64_t gart_size; + + struct radeon_memory *bo_list[2]; + struct radeon_memory *front_buffer; + struct radeon_memory *back_buffer; + struct radeon_memory *depth_buffer; + +#if 0 + struct radeon_memory *exa_buffer; +#endif + struct radeon_memory *texture_buffer; + + struct radeon_memory *dma_buffer; + struct radeon_memory *gart_texture_buffer; + struct radeon_memory *rotate_buffer; + struct radeon_memory *cursor[2]; + + /* indirect buffer for accel */ + struct radeon_memory *gem_ib_memory; + + } mm; + + drm_handle_t fb_map_handle; + Bool drm_mode_setting; +#ifdef XF86DRM_MODE + drmmode_rec drmmode; +#endif + + dri_bufmgr *bufmgr; } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ @@ -1030,6 +1102,23 @@ extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode); extern void RADEONInitVideo(ScreenPtr pScreen); extern void RADEONResetVideo(ScrnInfoPtr pScrn); +/* radeon_memory.c */ +extern uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem); +extern Bool radeon_bind_all_memory(ScrnInfoPtr pScrn); +extern Bool radeon_unbind_all_memory(ScrnInfoPtr pScrn); +extern struct radeon_memory *radeon_allocate_memory(ScrnInfoPtr pScrn, int pool, int size, int alignment, Bool no_backing_store, char *name, + int need_bind); +uint32_t radeon_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch); +int radeon_map_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +void radeon_unmap_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +void radeon_free_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +Bool radeon_bind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +Bool radeon_free_all_memory(ScrnInfoPtr pScrn); +Bool radeon_setup_kernel_mem(ScreenPtr pScreen); +Bool RADEONDRIDoMappings(ScreenPtr pScreen); +Bool radeon_update_dri_buffers(ScrnInfoPtr pScrn); +Bool radeon_setup_gart_mem(ScreenPtr pScreen); + #ifdef XF86DRI # ifdef USE_XAA /* radeon_accelfuncs.c */ @@ -1048,7 +1137,9 @@ do { \ #define RADEONCP_RELEASE(pScrn, info) \ do { \ - if (info->CPInUse) { \ + if (info->new_cs) { \ + RADEONCPReleaseIndirect(pScrn); \ + } else if (info->CPInUse) { \ RADEON_PURGE_CACHE(); \ RADEON_WAIT_UNTIL_IDLE(); \ RADEONCPReleaseIndirect(pScrn); \ @@ -1082,7 +1173,7 @@ do { \ #define RADEONCP_REFRESH(pScrn, info) \ do { \ - if (!info->CPInUse) { \ + if (!info->CPInUse && !info->new_cs) { \ if (info->needCacheFlush) { \ RADEON_PURGE_CACHE(); \ RADEON_PURGE_ZCACHE(); \ @@ -1109,6 +1200,13 @@ do { \ #define RING_LOCALS uint32_t *__head = NULL; int __expected; int __count = 0 #define BEGIN_RING(n) do { \ + if (!info->indirectBuffer) { \ + info->indirectBuffer = RADEONCPGetBuffer(pScrn); \ + info->indirectStart = 0; \ + } else if (info->indirectBuffer->used + (n) * (int)sizeof(uint32_t) > \ + info->indirectBuffer->total) { \ + RADEONCPFlushIndirect(pScrn, 1); \ + } \ if (RADEON_VERBOSE) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\ @@ -1121,13 +1219,6 @@ do { \ } \ info->dma_debug_func = __FILE__; \ info->dma_debug_lineno = __LINE__; \ - if (!info->indirectBuffer) { \ - info->indirectBuffer = RADEONCPGetBuffer(pScrn); \ - info->indirectStart = 0; \ - } else if (info->indirectBuffer->used + (n) * (int)sizeof(uint32_t) > \ - info->indirectBuffer->total) { \ - RADEONCPFlushIndirect(pScrn, 1); \ - } \ __expected = n; \ __head = (pointer)((char *)info->indirectBuffer->address + \ info->indirectBuffer->used); \ @@ -1170,6 +1261,14 @@ do { \ OUT_RING(val); \ } while (0) +/* TODO - VRAM is wrong in general but true for now - all EXA stuff + is in VRAM */ +#define OUT_RING_RELOC(x, read_domains, write_domains) \ + do { \ + radeon_bufmgr_emit_reloc(x, __head, &__count, read_domains, write_domains); \ + } while(0) + + #define FLUSH_RING() \ do { \ if (RADEON_VERBOSE) \ diff --git a/src/radeon_accel.c b/src/radeon_accel.c index e617fd5..dfb88a6 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -313,6 +313,9 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + if (info->drm_mode_setting) + return; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "EngineRestore (%d/%d)\n", info->CurrentLayout.pixel_code, @@ -371,7 +374,7 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) info->CurrentLayout.bitsPerPixel); #ifdef XF86DRI - if (info->directRenderingEnabled && (IS_R300_3D || IS_R500_3D)) { + if ((info->directRenderingEnabled || info->drm_mode_setting) && (IS_R300_3D || IS_R500_3D)) { drmRadeonGetParam np; int num_pipes; @@ -391,60 +394,63 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) } #endif - if ((info->ChipFamily == CHIP_FAMILY_RV410) || - (info->ChipFamily == CHIP_FAMILY_R420) || - (info->ChipFamily == CHIP_FAMILY_RS600) || - (info->ChipFamily == CHIP_FAMILY_RS690) || - (info->ChipFamily == CHIP_FAMILY_RS740) || - (info->ChipFamily == CHIP_FAMILY_RS400) || - (info->ChipFamily == CHIP_FAMILY_RS480) || - IS_R500_3D) { - if (info->num_gb_pipes == 0) { - uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT); - - info->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; - if (IS_R500_3D) - OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); - } - } else { - if (info->num_gb_pipes == 0) { - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350)) { - /* R3xx chips */ - info->num_gb_pipes = 2; - } else { - /* RV3xx chips */ - info->num_gb_pipes = 1; + if (!info->drm_mode_setting) { + if ((info->ChipFamily == CHIP_FAMILY_RV410) || + (info->ChipFamily == CHIP_FAMILY_R420) || + (info->ChipFamily == CHIP_FAMILY_RS600) || + (info->ChipFamily == CHIP_FAMILY_RS690) || + (info->ChipFamily == CHIP_FAMILY_RS740) || + (info->ChipFamily == CHIP_FAMILY_RS400) || + (info->ChipFamily == CHIP_FAMILY_RS480) || + IS_R500_3D) { + if (info->num_gb_pipes == 0) { + uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT); + + info->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; + if (IS_R500_3D) + OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); + } + } else { + if (info->num_gb_pipes == 0) { + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350)) { + /* R3xx chips */ + info->num_gb_pipes = 2; + } else { + /* RV3xx chips */ + info->num_gb_pipes = 1; + } } } + + if (IS_R300_3D || IS_R500_3D) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "num pipes is %d\n", info->num_gb_pipes); + + if (IS_R300_3D || IS_R500_3D) { + uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16); + + switch(info->num_gb_pipes) { + case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; + case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; + case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; + default: + case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; + } + + OUTREG(R300_GB_TILE_CONFIG, gb_tile_config); + OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); + if (info->ChipFamily >= CHIP_FAMILY_R420) + OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); + OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) | + R300_DC_AUTOFLUSH_ENABLE | + R300_DC_DC_DISABLE_IGNORE_PE)); + } else + OUTREG(RADEON_RB3D_CNTL, 0); + + RADEONEngineReset(pScrn); } - if (IS_R300_3D || IS_R500_3D) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "num pipes is %d\n", info->num_gb_pipes); - - if (IS_R300_3D || IS_R500_3D) { - uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16); - - switch(info->num_gb_pipes) { - case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; - case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; - case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; - default: - case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; - } - - OUTREG(R300_GB_TILE_CONFIG, gb_tile_config); - OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); - OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) | - R300_DC_AUTOFLUSH_ENABLE | - R300_DC_DC_DISABLE_IGNORE_PE)); - } else - OUTREG(RADEON_RB3D_CNTL, 0); - - RADEONEngineReset(pScrn); - switch (info->CurrentLayout.pixel_code) { case 8: info->datatype = 2; break; case 15: info->datatype = 3; break; @@ -556,6 +562,149 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info) } } +drmBufPtr RADEONCSGetBuffer(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->ib_gem_fake.address = xcalloc(1, RADEON_BUFFER_SIZE); + if (!info->ib_gem_fake.address) + return NULL; + + info->ib_gem_fake.used = 0; + info->ib_gem_fake.total = RADEON_BUFFER_SIZE - (16*4); // reserve 16 dwords + return &info->ib_gem_fake; +} + +void RADEONCSFlushIndirect(ScrnInfoPtr pScrn, int discard) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_radeon_cs args; + int ret; + RING_LOCALS; + + /* always add the cache flushes to the end of the IB */ + info->indirectBuffer->total += 16 * 4; + + /* end of IB purge caches */ + if (info->cs_used_depth) { + RADEON_PURGE_ZCACHE(); + info->cs_used_depth = 0; + } + + RADEON_PURGE_CACHE(); + RADEON_WAIT_UNTIL_IDLE(); + + args.packets = (unsigned long)info->ib_gem_fake.address; + args.dwords = info->indirectBuffer->used / sizeof(uint32_t); + + ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_CS, + &args, sizeof(args)); + + if (ret) { + FatalError("DRM Command submission failure %d\n", ret); + return; + } + + + info->indirectStart = 0; + info->indirectBuffer->used = 0; + info->indirectBuffer->total -= 16*4; + + if (info->bufmgr) + radeon_gem_bufmgr_post_submit(info->bufmgr); + + /* copy some state into the buffer now - we need to add 2D state to each + buffer as the kernel needs to use the blit engine to move stuff around */ + if (info->reemit_current2d) + info->reemit_current2d(pScrn, 0); +} + +void RADEONCSReleaseIndirect(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (!info->indirectBuffer) return; + RADEONCSFlushIndirect(pScrn, 0); + xfree(info->ib_gem_fake.address); + info->ib_gem_fake.address = NULL; + info->indirectBuffer = NULL; + +} + +drmBufPtr RADEONGEMGetBuffer(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int ret; + + info->mm.gem_ib_memory = radeon_allocate_memory(pScrn, RADEON_POOL_GART, RADEON_BUFFER_SIZE, + 0, 0, "Accel IB", 0); + + if (!info->mm.gem_ib_memory) { + ErrorF("Unable to map allocate IB\n"); + return NULL; + } + + radeon_bind_memory(pScrn, info->mm.gem_ib_memory); + ret = radeon_map_memory(pScrn, info->mm.gem_ib_memory); + if (ret) { + ErrorF("Unable to map IB\n"); + radeon_free_memory(pScrn, info->mm.gem_ib_memory); + return NULL; + } + info->ib_gem_fake.address = info->mm.gem_ib_memory->map; + info->ib_gem_fake.used = 0; + info->ib_gem_fake.total = RADEON_BUFFER_SIZE; + + return &info->ib_gem_fake; +} + +void RADEONGEMFlushIndirect(ScrnInfoPtr pScrn, int discard) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_radeon_gem_indirect args; + struct drm_radeon_gem_set_domain dom_args; + + if (RADEON_VERBOSE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing IB\n"); + } + + args.handle = info->mm.gem_ib_memory->kernel_bo_handle; + args.used = info->indirectBuffer->used; + + + drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_INDIRECT, + &args, sizeof(args)); + + /* for now just wait for the buffer to come around again */ + + dom_args.handle = info->mm.gem_ib_memory->kernel_bo_handle; + dom_args.read_domains = RADEON_GEM_DOMAIN_GTT; + dom_args.write_domain = 0; + + drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_SET_DOMAIN, + &dom_args, sizeof(dom_args)); + + info->indirectStart = 0; + info->indirectBuffer->used = 0; +} + +void RADEONGEMReleaseIndirect(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (RADEON_VERBOSE) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing IB\n"); + } + + if (!info->indirectBuffer) return; + + RADEONGEMFlushIndirect(pScrn, 0); + + radeon_free_memory(pScrn, info->mm.gem_ib_memory); + info->mm.gem_ib_memory = NULL; + info->indirectBuffer = NULL; +} + /* Get an indirect buffer for the CP 2D acceleration commands */ drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn) { @@ -566,6 +715,9 @@ drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn) int size = 0; int i = 0; int ret; + + if (info->new_cs) + return RADEONCSGetBuffer(pScrn); #if 0 /* FIXME: pScrn->pScreen has not been initialized when this is first @@ -631,6 +783,11 @@ void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard) if (!buffer) return; if (start == buffer->used && !discard) return; + if (info->new_cs) { + RADEONCSFlushIndirect(pScrn, discard); + return; + } + if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n", buffer->idx); @@ -665,10 +822,17 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn) int start = info->indirectStart; drmRadeonIndirect indirect; + + if (info->new_cs) { + RADEONCSReleaseIndirect(pScrn); + return; + } + info->indirectBuffer = NULL; info->indirectStart = 0; if (!buffer) return; + if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n", @@ -795,6 +959,7 @@ RADEONHostDataBlit( ret = ( uint8_t* )&__head[__count]; __count += dwords; + ADVANCE_RING(); *y += *hpass; @@ -932,7 +1097,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen) #ifdef USE_EXA if (info->useEXA) { # ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled || info->drm_mode_setting) { if (!RADEONDrawInitCP(pScreen)) return FALSE; } else @@ -953,7 +1118,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen) } #ifdef XF86DRI - if (info->directRenderingEnabled) + if (info->directRenderingEnabled || info->drm_mode_setting) RADEONAccelInitCP(pScreen, a); else #endif /* XF86DRI */ @@ -975,11 +1140,13 @@ void RADEONInit3DEngine(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR (pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { - RADEONSAREAPrivPtr pSAREAPriv; - - pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + if (info->directRenderingEnabled || info->drm_mode_setting) { + if (info->directRenderingEnabled) { + RADEONSAREAPrivPtr pSAREAPriv; + + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen); + } RADEONInit3DEngineCP(pScrn); } else #endif diff --git a/src/radeon_bufmgr.h b/src/radeon_bufmgr.h new file mode 100644 index 0000000..3d28992 --- /dev/null +++ b/src/radeon_bufmgr.h @@ -0,0 +1,30 @@ +/** + * @file intel_bufmgr.h + * + * Public definitions of Intel-specific bufmgr functions. + */ + +#ifndef RADEON_BUFMGR_H +#define RADEON_BUFMGR_H + +#include "radeon_dri_bufmgr.h" + +struct radeon_bufmgr { + void (*emit_reloc)(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); +}; + +dri_bufmgr *radeon_bufmgr_gem_init(int fd); +dri_bo *radeon_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, + unsigned int handle); + +void radeon_bufmgr_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); + +dri_bufmgr *radeon_bufmgr_exa_init(ScrnInfoPtr pScrn); +extern void radeon_bufmgr_exa_wait_rendering(dri_bo *bo); +extern dri_bo *radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem); +void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr); +void radeon_bufmgr_pin(dri_bo *buf); +void radeon_bufmgr_unpin(dri_bo *buf); +uint32_t radeon_bufmgr_get_handle(dri_bo *buf); +void radeon_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr); +#endif diff --git a/src/radeon_bufmgr_exa.c b/src/radeon_bufmgr_exa.c new file mode 100644 index 0000000..df9dc81 --- /dev/null +++ b/src/radeon_bufmgr_exa.c @@ -0,0 +1,323 @@ +/************************************************************************** + * + * Copyright © 2007-2008 Red Hat Inc. + * Copyright © 2007 Intel Corporation + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ +/* + * Authors: Thomas Hellström + * Keith Whitwell + * Eric Anholt + * Dave Airlie + * Kristian Høgsberg + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "xf86.h" +#include "errno.h" +#include "string.h" + +#include "radeon_reg.h" +#include "radeon_probe.h" +#include "radeon.h" +#include "radeon_bufmgr.h" + + +typedef struct _dri_bo_exa { + dri_bo bo; + struct radeon_memory *mem; + int refcount; + int reloc_count; + int map_count; + /* reloc list - add to list for relocs */ + struct _dri_bo_exa *next; +} dri_bo_exa; + +typedef struct _dri_bufmgr_exa { + dri_bufmgr bufmgr; + struct radeon_bufmgr radeon_bufmgr; + ScrnInfoPtr pScrn; + struct _dri_bo_exa *reloc_head; +} dri_bufmgr_exa; + +static dri_bo * +dri_exa_alloc(dri_bufmgr *bufmgr, const char *name, + unsigned long size, unsigned int alignment) + +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)bufmgr; + RADEONInfoPtr info = RADEONPTR(bufmgr_exa->pScrn); + dri_bo_exa *exa_buf; + + exa_buf = malloc(sizeof(*exa_buf)); + if (!exa_buf) + return NULL; + + exa_buf->refcount = 1; + exa_buf->mem = radeon_allocate_memory(bufmgr_exa->pScrn, RADEON_POOL_GART, + size, alignment, 0, name, 0); + + exa_buf->bo.size = exa_buf->mem->size; + exa_buf->bo.offset = exa_buf->mem->offset; + exa_buf->bo.bufmgr = bufmgr; + exa_buf->next = NULL; + exa_buf->reloc_count = 0; + exa_buf->map_count = 0; + + return &exa_buf->bo; +} + +static void +dri_exa_bo_reference(dri_bo *buf) +{ + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + exa_buf->refcount++; +} + +static void +dri_exa_bo_unreference(dri_bo *buf) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + + if (!buf) + return; + + if (--exa_buf->refcount == 0) + radeon_free_memory(bufmgr_exa->pScrn, exa_buf->mem); +} + +static int +dri_exa_bo_map(dri_bo *buf, int write_enable) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + + if (exa_buf->map_count++ != 0) + return 0; + + radeon_map_memory(bufmgr_exa->pScrn, exa_buf->mem); + exa_buf->bo.virtual = exa_buf->mem->map; + return 0; +} + +static int +dri_exa_bo_unmap(dri_bo *buf) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + + if (--exa_buf->map_count > 0) + return 0; + + radeon_unmap_memory(bufmgr_exa->pScrn, exa_buf->mem); + exa_buf->bo.virtual = 0; + return 0; +} + +static void +dri_bufmgr_exa_destroy(dri_bufmgr *bufmgr) +{ + free(bufmgr); +} + +void radeon_bufmgr_exa_wait_rendering(dri_bo *buf) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + RADEONInfoPtr info = RADEONPTR(bufmgr_exa->pScrn); + struct drm_radeon_gem_set_domain dom_args; + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + int ret; + + dom_args.handle = exa_buf->mem->kernel_bo_handle; + dom_args.read_domains = RADEON_GEM_DOMAIN_GTT; + dom_args.write_domain = 0; + ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_SET_DOMAIN, + &dom_args, sizeof(dom_args)); + + return; +} + +int radeon_bufmgr_subdata(dri_bo *buf, unsigned long offset, + unsigned long size, const void *data) +{ + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + RADEONInfoPtr info = RADEONPTR(bufmgr_exa->pScrn); + int ret; + /* go to pwrite */ + struct drm_radeon_gem_pwrite pwrite; + + pwrite.handle = exa_buf->mem->kernel_bo_handle; + pwrite.offset = offset; + pwrite.size = size; + pwrite.data_ptr = (uint64_t)(uintptr_t)data; + + do { + ret = drmCommandWriteRead(info->drmFD, DRM_IOCTL_RADEON_GEM_PWRITE, + &pwrite, sizeof(pwrite)); + } while (ret == -1 && errno == EINTR); + + if (ret != 0) { + fprintf(stderr,"Pwrite %lx at %lx failed\n", size, offset); + return -1; + } + return 0; +} + + +dri_bo * +radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)bufmgr; + dri_bo_exa *exa_buf; + + exa_buf = malloc(sizeof(*exa_buf)); + if (!exa_buf) + return NULL; + exa_buf->refcount = 1; + exa_buf->mem = mem; + exa_buf->bo.size = exa_buf->mem->size; + exa_buf->bo.offset = exa_buf->mem->offset; + exa_buf->bo.bufmgr = bufmgr; + exa_buf->bo.virtual = exa_buf->mem->map; + exa_buf->next = NULL; + exa_buf->reloc_count = 0; + /* get map count right */ + exa_buf->map_count = 1; + + return &exa_buf->bo; +} + +static void radeon_bufmgr_exa_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + ScrnInfoPtr pScrn = bufmgr_exa->pScrn; + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + uint32_t *__head = head; + uint32_t __count = *count_p; + dri_bo_exa *trav; + + if (exa_buf->reloc_count == 0) { + dri_bo_reference(buf); + + if (bufmgr_exa->reloc_head == NULL) + bufmgr_exa->reloc_head = exa_buf; + else { + trav = bufmgr_exa->reloc_head; + while (trav->next != NULL) + trav = trav->next; + trav->next = exa_buf; + } + } + exa_buf->reloc_count++; + OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 2)); + OUT_RING(exa_buf->mem->kernel_bo_handle); + OUT_RING(read_domains); + OUT_RING(write_domain); + *count_p = __count; +} + +/** + * Initializes the EXA buffer manager, which is just a thin wrapper + * around the EXA allocator. + * + * \param fd File descriptor of the opened DRM device. + * \param fence_type Driver-specific fence type used for fences with no flush. + * \param fence_type_flush Driver-specific fence type used for fences with a + * flush. + */ +dri_bufmgr * +radeon_bufmgr_exa_init(ScrnInfoPtr pScrn) +{ + dri_bufmgr_exa *bufmgr_exa; + + bufmgr_exa = calloc(1, sizeof(*bufmgr_exa)); + bufmgr_exa->pScrn = pScrn; + + bufmgr_exa->bufmgr.bo_alloc = dri_exa_alloc; + bufmgr_exa->bufmgr.bo_reference = dri_exa_bo_reference; + bufmgr_exa->bufmgr.bo_unreference = dri_exa_bo_unreference; + bufmgr_exa->bufmgr.bo_map = dri_exa_bo_map; + bufmgr_exa->bufmgr.bo_unmap = dri_exa_bo_unmap; + bufmgr_exa->bufmgr.destroy = dri_bufmgr_exa_destroy; + //bufmgr_exa->bufmgr.bo_wait_rendering = radeon_bufmgr_exa_wait_rendering; + bufmgr_exa->radeon_bufmgr.emit_reloc = radeon_bufmgr_exa_emit_reloc; + return &bufmgr_exa->bufmgr; +} + +void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)bufmgr; + struct _dri_bo_exa *trav, *prev; + + if (!bufmgr_exa->reloc_head) + return; + + trav = bufmgr_exa->reloc_head; + while (trav) { + prev = trav; + trav = trav->next; + + prev->reloc_count = 0; + prev->next = NULL; + dri_bo_unreference(&prev->bo); + } + bufmgr_exa->reloc_head = NULL; + +} + +void radeon_bufmgr_pin(dri_bo *buf) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + + radeon_bind_memory(bufmgr_exa->pScrn, exa_buf->mem); +} + +void radeon_bufmgr_unpin(dri_bo *buf) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + + radeon_unbind_memory(bufmgr_exa->pScrn, exa_buf->mem); +} + +uint32_t radeon_bufmgr_get_handle(dri_bo *buf) +{ + dri_bo_exa *exa_buf = (dri_bo_exa *)buf; + + return exa_buf->mem->kernel_bo_handle; +} diff --git a/src/radeon_bufmgr_exa.h b/src/radeon_bufmgr_exa.h new file mode 100644 index 0000000..0d79b58 --- /dev/null +++ b/src/radeon_bufmgr_exa.h @@ -0,0 +1,14 @@ +#ifndef RADEON_BUFMGR_EXA_H +#define RADEON_BUFMGR_EXA_H + +#include "radeon_dri_bufmgr.h" + +dri_bufmgr *radeon_bufmgr_exa_init(ScrnInfoPtr pScrn); +extern void radeon_bufmgr_exa_wait_rendering(dri_bo *bo); +extern dri_bo *radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem); +void radeon_bufmgr_exa_emit_reloc(dri_bo *bo, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); +void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr); +void radeon_bufmgr_pin(dri_bo *buf); +void radeon_bufmgr_unpin(dri_bo *buf); +uint32_t radeon_bufmgr_get_handle(dri_bo *buf); +#endif diff --git a/src/radeon_bufmgr_gem.c b/src/radeon_bufmgr_gem.c new file mode 100644 index 0000000..7fed98b --- /dev/null +++ b/src/radeon_bufmgr_gem.c @@ -0,0 +1,536 @@ +/************************************************************************** + * + * Copyright © 2007-2008 Red Hat Inc. + * Copyright © 2007 Intel Corporation + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ +/* + * Authors: Thomas Hellström + * Keith Whitwell + * Eric Anholt + * Dave Airlie + * Kristian Høgsberg + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xf86.h" +#include "errno.h" +#include "string.h" + +#include "radeon_reg.h" +#include "radeon_probe.h" +#include "radeon.h" +#include "radeon_bufmgr.h" + +#define DBG(...) do { \ + if (bufmgr_gem->bufmgr.debug) \ + fprintf(stderr, __VA_ARGS__); \ +} while (0) + +typedef struct _dri_bo_gem { + dri_bo bo; + int refcount; + int reloc_count; + int map_count; + /* reloc list - add to list for relocs */ + uint32_t gem_handle; + const char *name; + struct _dri_bo_gem *next; + struct _dri_bo_gem *reloc_next; + int in_vram; /* have we migrated this bo to VRAM ever */ +} dri_bo_gem; + +struct dri_gem_bo_bucket { + dri_bo_gem *head, **tail; + /** + * Limit on the number of entries in this bucket. + * + * 0 means that this caching at this bucket size is disabled. + * -1 means that there is no limit to caching at this size. + */ + int max_entries; + int num_entries; +}; + +/* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse + * is 1 << 16 pages, or 256MB. + */ +#define RADEON_GEM_BO_BUCKETS 16 + +typedef struct _dri_bufmgr_gem { + dri_bufmgr bufmgr; + struct radeon_bufmgr radeon_bufmgr; + int fd; + struct _dri_bo_gem *reloc_head; + + /** Array of lists of cached gem objects of power-of-two sizes */ + struct dri_gem_bo_bucket cache_bucket[RADEON_GEM_BO_BUCKETS]; +} dri_bufmgr_gem; + +static int +logbase2(int n) +{ + int i = 1; + int log2 = 0; + + while (n > i) { + i *= 2; + log2++; + } + + return log2; +} + +static struct dri_gem_bo_bucket * +dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size) +{ + int i; + + /* We only do buckets in power of two increments */ + if ((size & (size - 1)) != 0) + return NULL; + + /* We should only see sizes rounded to pages. */ + assert((size % 4096) == 0); + + /* We always allocate in units of pages */ + i = ffs(size / 4096) - 1; + if (i >= RADEON_GEM_BO_BUCKETS) + return NULL; + + return &bufmgr_gem->cache_bucket[i]; +} + + +static dri_bo * +dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name, + unsigned long size, unsigned int alignment) + +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + struct drm_radeon_gem_create args; + int ret; + unsigned int page_size = getpagesize(); + dri_bo_gem *gem_bo; + struct dri_gem_bo_bucket *bucket; + int alloc_from_cache = 0; + unsigned long bo_size; + + /* Round the allocated size up to a power of two number of pages. */ + bo_size = 1 << logbase2(size); + if (bo_size < page_size) + bo_size = page_size; + bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_size); + + /* If we don't have caching at this size, don't actually round the + * allocation up. + */ + if (bucket == NULL || bucket->max_entries == 0) { + bo_size = size; + if (bo_size < page_size) + bo_size = page_size; + } + + /* Get a buffer out of the cache if available */ + if (bucket != NULL && bucket->num_entries > 0) { + struct drm_radeon_gem_set_domain args; + + gem_bo = bucket->head; + args.handle = gem_bo->gem_handle; + args.read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM; + args.write_domain = 0; + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_RADEON_GEM_SET_DOMAIN, &args); + alloc_from_cache = (ret == 0); + + if (alloc_from_cache) { + bucket->head = gem_bo->next; + if (gem_bo->next == NULL) + bucket->tail = &bucket->head; + bucket->num_entries--; + } + } + + if (!alloc_from_cache) { + + gem_bo = calloc(1, sizeof(*gem_bo)); + if (!gem_bo) + return NULL; + + gem_bo->bo.size = bo_size; + args.size = bo_size; + args.alignment = alignment; + args.initial_domain = RADEON_GEM_DOMAIN_CPU; + args.no_backing_store = 0; + + ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_CREATE, &args, sizeof(args)); + gem_bo->gem_handle = args.handle; + if (ret != 0) { + free(gem_bo); + return NULL; + } + gem_bo->bo.bufmgr = bufmgr; + } + + gem_bo->refcount = 1; + gem_bo->reloc_count = 0; + gem_bo->map_count = 0; + gem_bo->in_vram = 0; + gem_bo->name = name; + + DBG("bo_create: buf %d (%s) %ldb: %d\n", + gem_bo->gem_handle, gem_bo->name, size, alloc_from_cache); + + return &gem_bo->bo; +} + +static void +dri_gem_bo_reference(dri_bo *bo) +{ + dri_bo_gem *gem_bo = (dri_bo_gem *)bo; + gem_bo->refcount++; +} + +static void dri_gem_bo_free(dri_bo *bo) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + dri_bo_gem *gem_bo = (dri_bo_gem *)bo; + struct drm_gem_close args; + + if (gem_bo->map_count) + munmap(gem_bo->bo.virtual, gem_bo->bo.size); + + /* close object */ + args.handle = gem_bo->gem_handle; + ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &args); + free(gem_bo); +} + +static void +dri_gem_bo_unreference(dri_bo *bo) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + dri_bo_gem *gem_bo = (dri_bo_gem *)bo; + + if (!bo) + return; + + if (--gem_bo->refcount == 0) { + struct dri_gem_bo_bucket *bucket; + + + bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size); + /* Put the buffer into our internal cache for reuse if we can. */ + if ((gem_bo->in_vram == 0) && (bucket != NULL && + (bucket->max_entries == -1 || + (bucket->max_entries > 0 && + bucket->num_entries < bucket->max_entries)))) + { + DBG("bo_unreference final: %d (%s) 1\n", + gem_bo->gem_handle, gem_bo->name); + + gem_bo->name = 0; + + gem_bo->next = NULL; + *bucket->tail = gem_bo; + bucket->tail = &gem_bo->next; + bucket->num_entries++; + } else { + DBG("bo_unreference final: %d (%s) 0 - free %d\n", + gem_bo->gem_handle, gem_bo->name, gem_bo->in_vram); + dri_gem_bo_free(bo); + } + + return; + } +} + +static int +dri_gem_bo_map(dri_bo *bo, int write_enable) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + dri_bo_gem *gem_bo = (dri_bo_gem *)bo; + struct drm_radeon_gem_mmap args; + int ret; + + if (gem_bo->map_count++ != 0) + return 0; + + args.handle = gem_bo->gem_handle; + args.offset = 0; + args.size = gem_bo->bo.size; + + ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_MMAP, &args, sizeof(args)); + if (!ret) + gem_bo->bo.virtual = (void *)(unsigned long)args.addr_ptr; + + return ret; +} + +static int +dri_gem_bo_unmap(dri_bo *buf) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr; + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + + if (--gem_bo->map_count > 0) + return 0; + + munmap(gem_bo->bo.virtual, gem_bo->bo.size); + gem_bo->bo.virtual = 0; + return 0; +} + +static void +dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + int i; + + /* Free any cached buffer objects we were going to reuse */ + for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) { + struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i]; + dri_bo_gem *bo_gem; + + while ((bo_gem = bucket->head) != NULL) { + bucket->head = bo_gem->next; + if (bo_gem->next == NULL) + bucket->tail = &bucket->head; + bucket->num_entries--; + + dri_gem_bo_free(&bo_gem->bo); + } + } + free(bufmgr); +} + +void radeon_bufmgr_gem_wait_rendering(dri_bo *buf) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr; + struct drm_radeon_gem_set_domain dom_args; + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + int ret; + + dom_args.handle = gem_bo->gem_handle; + dom_args.read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM; + dom_args.write_domain = 0; + ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_SET_DOMAIN, + &dom_args, sizeof(dom_args)); + return; +} + +/** + * Returns a dri_bo wrapping the given buffer object handle. + * + * This can be used when one application needs to pass a buffer object + * to another. + */ +dri_bo * +radeon_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, + unsigned int handle) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + dri_bo_gem *bo_gem; + int ret; + struct drm_gem_open open_arg; + + bo_gem = calloc(1, sizeof(*bo_gem)); + if (!bo_gem) + return NULL; + + memset(&open_arg, 0, sizeof(open_arg)); + open_arg.name = handle; + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg); + if (ret != 0) { + fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n", + name, handle, strerror(-ret)); + free(bo_gem); + return NULL; + } + bo_gem->bo.size = open_arg.size; + bo_gem->bo.offset = 0; + bo_gem->bo.virtual = NULL; + bo_gem->bo.bufmgr = bufmgr; + bo_gem->name = name; + bo_gem->refcount = 1; + bo_gem->gem_handle = open_arg.handle; + + return &bo_gem->bo; +} + +#define BUF_OUT_RING(x) do { \ + __head[__count++] = (x); \ + } while (0) + +void radeon_bufmgr_gem_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr; + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + uint32_t *__head = head; + uint32_t __count = *count_p; + dri_bo_gem *trav; + + if (gem_bo->reloc_count == 0) { + dri_bo_reference(buf); + + if (bufmgr_gem->reloc_head == NULL) + bufmgr_gem->reloc_head = gem_bo; + else { + trav = bufmgr_gem->reloc_head; + while (trav->reloc_next != NULL) + trav = trav->reloc_next; + trav->reloc_next = gem_bo; + } + } + + if (write_domain == RADEON_GEM_DOMAIN_VRAM) { + if (gem_bo->in_vram == 0) + DBG("bo_into vram: buf %d (%s) %d %d\n", + gem_bo->gem_handle, gem_bo->name, read_domains, write_domain); + + gem_bo->in_vram = 1; + } + + gem_bo->reloc_count++; + BUF_OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 2)); + BUF_OUT_RING(gem_bo->gem_handle); + BUF_OUT_RING(read_domains); + BUF_OUT_RING(write_domain); + *count_p = __count; +} + +/** + * Enables unlimited caching of buffer objects for reuse. + * + * This is potentially very memory expensive, as the cache at each bucket + * size is only bounded by how many buffers of that size we've managed to have + * in flight at once. + */ +void +radeon_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + int i; + + for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) { + bufmgr_gem->cache_bucket[i].max_entries = -1; + } +} + +/** + * Initializes the GEM buffer manager, which is just a thin wrapper + * around the GEM allocator. + * + * \param fd File descriptor of the opened DRM device. + * \param fence_type Driver-specific fence type used for fences with no flush. + * \param fence_type_flush Driver-specific fence type used for fences with a + * flush. + */ +dri_bufmgr * +radeon_bufmgr_gem_init(int fd) +{ + dri_bufmgr_gem *bufmgr_gem; + int i; + + bufmgr_gem = calloc(1, sizeof(*bufmgr_gem)); + bufmgr_gem->fd = fd; + + bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc; + bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference; + bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference; + bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map; + bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap; + bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy; + //bufmgr_gem->bufmgr.bo_wait_rendering = radeon_bufmgr_gem_wait_rendering; + bufmgr_gem->radeon_bufmgr.emit_reloc = radeon_bufmgr_gem_emit_reloc; + /* Initialize the linked lists for BO reuse cache. */ + for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) + bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head; + bufmgr_gem->bufmgr.debug = 1; + return &bufmgr_gem->bufmgr; +} + + +void radeon_gem_bufmgr_post_submit(dri_bufmgr *bufmgr) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + struct _dri_bo_gem *trav, *prev; + + if (!bufmgr_gem->reloc_head) + return; + + trav = bufmgr_gem->reloc_head; + while (trav) { + prev = trav; + trav = trav->reloc_next; + + prev->reloc_count = 0; + prev->reloc_next = NULL; + dri_bo_unreference(&prev->bo); + } + bufmgr_gem->reloc_head = NULL; + +} + +void radeon_gem_bufmgr_pin(dri_bo *buf) +{ +} + +void radeon_gem_bufmgr_unpin(dri_bo *buf) +{ +} + +uint32_t radeon_gem_bufmgr_get_handle(dri_bo *buf) +{ + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + + return gem_bo->gem_handle; +} + +void radeon_bufmgr_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain) +{ + struct radeon_bufmgr *radeon_bufmgr; + + radeon_bufmgr = (struct radeon_bufmgr *)(buf->bufmgr + 1); + radeon_bufmgr->emit_reloc(buf, head, count_p, read_domains, write_domain); +} + +int radeon_bufmgr_gem_in_vram(dri_bo *buf) +{ + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + + return gem_bo->in_vram; +} diff --git a/src/radeon_bufmgr_gem.h b/src/radeon_bufmgr_gem.h new file mode 100644 index 0000000..4c74c28 --- /dev/null +++ b/src/radeon_bufmgr_gem.h @@ -0,0 +1,14 @@ +#ifndef RADEON_BUFMGR_GEM_H +#define RADEON_BUFMGR_GEM_H + +#include "radeon_dri_bufmgr.h" + +extern void radeon_bufmgr_gem_wait_rendering(dri_bo *bo); +extern dri_bo *radeon_bufmgr_gem_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem); +void radeon_bufmgr_gem_emit_reloc(dri_bo *bo, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); +void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr); +void radeon_bufmgr_pin(dri_bo *buf); +void radeon_bufmgr_unpin(dri_bo *buf); +uint32_t radeon_bufmgr_get_handle(dri_bo *buf); +int radeon_bufmgr_gem_in_vram(dri_bo *buf); +#endif diff --git a/src/radeon_common.h b/src/radeon_common.h index 193c1f9..c3b7e3b 100644 --- a/src/radeon_common.h +++ b/src/radeon_common.h @@ -39,6 +39,9 @@ #include #include "xf86drm.h" +#include "radeon_drm.h" + +#if 0 /* WARNING: If you change any of these defines, make sure to change * the kernel include file as well (radeon_drm.h) */ @@ -494,3 +497,13 @@ typedef struct drm_radeon_surface_free { #define DRM_RADEON_VBLANK_CRTC2 2 #endif + +typedef drm_radeon_indirect_t drmRadeonIndirect; +typedef drm_radeon_getparam_t drmRadeonGetParam; +typedef drm_radeon_cp_stop_t drmRadeonCPStop; +typedef drm_radeon_surface_alloc_t drmRadeonSurfaceAlloc; +typedef drm_radeon_surface_free_t drmRadeonSurfaceFree; +typedef drm_radeon_init_t drmRadeonInit; +typedef drm_radeon_mem_init_heap_t drmRadeonMemInitHeap; +typedef drm_radeon_setparam_t drmRadeonSetParam; +#endif diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c index 1de6bf8..6ead191 100644 --- a/src/radeon_commonfuncs.c +++ b/src/radeon_commonfuncs.c @@ -61,12 +61,15 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) info->texW[0] = info->texH[0] = info->texW[1] = info->texH[1] = 1; if (IS_R300_3D || IS_R500_3D) { + int size; - BEGIN_ACCEL(3); - OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D); - OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE); - OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - FINISH_ACCEL(); + if (!info->new_cs) { + BEGIN_ACCEL(3); + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D); + OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE); + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); + FINISH_ACCEL(); + } gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16); @@ -78,10 +81,12 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; } - BEGIN_ACCEL(5); + size = (info->ChipFamily >= CHIP_FAMILY_R420) ? 5 : 4; + BEGIN_ACCEL(size); OUT_ACCEL_REG(R300_GB_TILE_CONFIG, gb_tile_config); OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG); + if (info->ChipFamily >= CHIP_FAMILY_R420) + OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG); OUT_ACCEL_REG(R300_GB_SELECT, 0); OUT_ACCEL_REG(R300_GB_ENABLE, 0); FINISH_ACCEL(); @@ -686,7 +691,7 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) #ifdef ACCEL_CP /* Make sure the CP is idle first */ - if (info->CPStarted) { + if (info->CPStarted || info->drm_mode_setting) { int ret; FLUSH_RING(); diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c index 13c2b9c..1e1835a 100644 --- a/src/radeon_cursor.c +++ b/src/radeon_cursor.c @@ -96,12 +96,19 @@ avivo_setup_cursor(xf86CrtcPtr crtc, Bool enable) RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; RADEONInfoPtr info = RADEONPTR(crtc->scrn); unsigned char *RADEONMMIO = info->MMIO; - + uint32_t location; + OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0); if (enable) { + + if (info->drm_mm) + location = info->fbLocation + radeon_crtc->cursor->offset; + else + location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset; + OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, - info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset); + location); OUTREG(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, ((CURSOR_WIDTH - 1) << 16) | (CURSOR_HEIGHT - 1)); OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, @@ -203,6 +210,7 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) int xorigin = 0, yorigin = 0; int stride = 256; DisplayModePtr mode = &crtc->mode; + uint32_t offset; if (x < 0) xorigin = -x+1; if (y < 0) yorigin = -y+1; @@ -235,8 +243,12 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) | (yorigin ? 0 : y))); RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n", radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); + if (info->drm_mm) + offset = radeon_crtc->cursor->offset; + else + offset = radeon_crtc->cursor_offset + pScrn->fbOffset; OUTREG(RADEON_CUR_OFFSET, - radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); + offset + yorigin * stride); } else if (crtc_id == 1) { OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) @@ -246,8 +258,12 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) | (yorigin ? 0 : y))); RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n", radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); + if (info->drm_mm) + offset = radeon_crtc->cursor->offset; + else + offset = radeon_crtc->cursor_offset + pScrn->fbOffset; OUTREG(RADEON_CUR2_OFFSET, - radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); + offset + yorigin * stride); } } } @@ -301,10 +317,15 @@ radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; RADEONInfoPtr info = RADEONPTR(pScrn); CURSOR_SWAPPING_DECL_MMIO - uint32_t *d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset); + uint32_t *d; RADEONCTRACE(("RADEONLoadCursorARGB\n")); + if (info->drm_mm) + d = (uint32_t *)radeon_crtc->cursor->map; + else + d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset); + info->cursor_argb = TRUE; CURSOR_SWAPPING_START(); @@ -336,7 +357,7 @@ Bool RADEONCursorInit(ScreenPtr pScreen) height = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes; #ifdef USE_XAA - if (!info->useEXA) { + if (!info->useEXA && !info->drm_mm) { int align = IS_AVIVO_VARIANT ? 4096 : 256; FBAreaPtr fbarea; diff --git a/src/radeon_dri.c b/src/radeon_dri.c index a192811..45414b4 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -40,6 +40,8 @@ #include #include +#include +#include /* Driver data structures */ #include "radeon.h" @@ -49,6 +51,8 @@ #include "radeon_dri.h" #include "radeon_version.h" +#include "radeon_drm.h" + /* X and server generic header files */ #include "xf86.h" #include "xf86PciInfo.h" @@ -62,17 +66,31 @@ static size_t radeon_drm_page_size; +#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)) +#define DRI_SUPPORTS_CLIP_NOTIFY 1 +#else +#define DRI_SUPPORTS_CLIP_NOTIFY 0 +#endif + +#if (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 4)) +#define DRI_DRIVER_FRAMEBUFFER_MAP 1 +#else +#define DRI_DRIVER_FRAMEBUFFER_MAP 0 +#endif static void RADEONDRITransitionTo2d(ScreenPtr pScreen); static void RADEONDRITransitionTo3d(ScreenPtr pScreen); static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen); static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen); +static Bool radeon_dri_gart_init(ScreenPtr pScreen); + #ifdef DAMAGE static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg); -#if (DRIINFO_MAJOR_VERSION > 5 || \ - (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)) +#if DRI_SUPPORTS_CLIP_NOTIFY static void RADEONDRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num); #endif #endif @@ -345,6 +363,125 @@ static void RADEONDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, #endif } + +uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_gem_flink flink; + int ret; + + if (mem && mem->kernel_bo_handle) { + if (!mem->kernel_name) { + flink.handle = mem->kernel_bo_handle; + ret = ioctl(info->drmFD, DRM_IOCTL_GEM_FLINK, &flink); + if (ret != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to name buffer %d\n", -errno); + return -1; + } + mem->kernel_name = flink.name; + } + return mem->kernel_name; + } + return -1; +} + +static void radeon_update_sarea(ScrnInfoPtr pScrn, RADEONSAREAPrivPtr sarea) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + sarea->front_handle = -1; + sarea->back_handle = -1; + sarea->depth_handle = -1; + + if (info->drm_mm){ + /* get handles and use them */ + sarea->front_handle = radeon_name_buffer(pScrn, info->mm.front_buffer); + + sarea->front_pitch = info->frontPitch * cpp; + sarea->back_pitch = info->backPitch * cpp; + sarea->depth_pitch = info->depthPitch * cpp; + ErrorF("front handle is %x\n", sarea->front_handle); + sarea->back_handle = radeon_name_buffer(pScrn, info->mm.back_buffer); + sarea->depth_handle = radeon_name_buffer(pScrn, info->mm.depth_buffer); + + } +} + +/* so we need to add a frontbuffer map no matter what */ +#define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y)) +#define ROUND_TO_PAGE(x) ROUND_TO((x), radeon_drm_page_size) + +static void +radeon_update_screen_private(ScrnInfoPtr pScrn, RADEONSAREAPrivPtr sarea) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONDRIPtr pRADEONDRI; + + pRADEONDRI = (RADEONDRIPtr)info->pDRIInfo->devPrivate; + info->pDRIInfo->frameBufferPhysicalAddress = (char *) info->LinearAddr; + info->pDRIInfo->frameBufferStride = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; + info->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes); +#if DRI_DRIVER_FRAMEBUFFER_MAP + info->pDRIInfo->hFrameBuffer = info->fb_map_handle; +#endif + /* overload these */ + pRADEONDRI->gartTexHandle = radeon_name_buffer(pScrn, info->mm.gart_texture_buffer); + pRADEONDRI->textureOffset = radeon_name_buffer(pScrn, info->mm.texture_buffer); + pRADEONDRI->frontOffset = radeon_name_buffer(pScrn, info->mm.front_buffer); + pRADEONDRI->backOffset = radeon_name_buffer(pScrn, info->mm.back_buffer); + pRADEONDRI->depthOffset = radeon_name_buffer(pScrn, info->mm.depth_buffer); +} + +static Bool +radeon_update_dri_mappings(ScrnInfoPtr pScrn, RADEONSAREAPrivPtr sarea) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + uint32_t fb_addr, fb_size; + int ret; + + if (!info->drm_mm) + return TRUE; + + + fb_addr = info->mm.front_buffer->offset + info->LinearAddr; + fb_size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes); + + if (info->fb_map_handle) { + drmRmMap(info->drmFD, info->fb_map_handle); + info->fb_map_handle = 0; + } + + ret = drmAddMap(info->drmFD, fb_addr, fb_size, DRM_FRAME_BUFFER, 0, + &info->fb_map_handle); + + ErrorF("adding fb map from %x for %x ret %d %x\n", fb_addr, fb_size, ret, info->fb_map_handle); + + if (ret < 0) + return FALSE; + + return TRUE; +} + +Bool radeon_update_dri_buffers(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + Bool success; + RADEONSAREAPrivPtr sarea = DRIGetSAREAPrivate(pScrn->pScreen); + + if (info->ChipFamily >= CHIP_FAMILY_R600) + return TRUE; + + success = radeon_update_dri_mappings(pScrn, sarea); + + if (!success) + return FALSE; + + radeon_update_sarea(pScrn, sarea); + radeon_update_screen_private(pScrn, sarea); + return TRUE; +} + /* Called when the X server is woken up to allow the last client's * context to be saved and the X server's context to be loaded. This is * not necessary for the Radeon since the client detects when it's @@ -362,7 +499,7 @@ static void RADEONEnterServer(ScreenPtr pScreen) RADEON_MARK_SYNC(info, pScrn); pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen)) { + if (pSAREAPriv->ctx_owner != DRIGetContext(pScrn->pScreen)) { info->XInited3D = FALSE; info->needCacheFlush = (info->ChipFamily >= CHIP_FAMILY_R300); } @@ -694,25 +831,37 @@ static void RADEONDRIInitGARTValues(RADEONInfoPtr info) info->gartOffset = 0; - /* Initialize the CP ring buffer data */ - info->ringStart = info->gartOffset; - info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size; - info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1; + if (!info->drm_mm) { + /* Initialize the CP ring buffer data */ + info->ringStart = info->gartOffset; + info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size; + info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1; - info->ringReadOffset = info->ringStart + info->ringMapSize; - info->ringReadMapSize = radeon_drm_page_size; + info->ringReadOffset = info->ringStart + info->ringMapSize; + info->ringReadMapSize = radeon_drm_page_size; /* Reserve space for vertex/indirect buffers */ - info->bufStart = info->ringReadOffset + info->ringReadMapSize; - info->bufMapSize = info->bufSize*1024*1024; - - /* Reserve the rest for GART textures */ - info->gartTexStart = info->bufStart + info->bufMapSize; - s = (info->gartSize*1024*1024 - info->gartTexStart); - l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - info->gartTexMapSize = (s >> l) << l; - info->log2GARTTexGran = l; + info->bufStart = info->ringReadOffset + info->ringReadMapSize; + info->bufMapSize = info->bufSize*1024*1024; + + /* Reserve the rest for GART textures */ + info->gartTexStart = info->bufStart + info->bufMapSize; + s = (info->gartSize*1024*1024 - info->gartTexStart); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + info->gartTexMapSize = (s >> l) << l; + info->log2GARTTexGran = l; + + } else { + s = (8*1024*1024); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + info->gartTexMapSize = (s >> l) << l; + info->log2GARTTexGran = l; + } + + } /* Set AGP transfer mode according to requests and constraints */ @@ -884,6 +1033,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] ring handle = 0x%08x\n", info->ringHandle); +#if 0 if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, &info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); @@ -892,7 +1042,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Ring mapped at 0x%08lx\n", (unsigned long)info->ring); - +#endif if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -903,6 +1053,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) "[agp] ring read ptr handle = 0x%08x\n", info->ringReadPtrHandle); +#if 0 if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, &info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -912,7 +1063,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Ring read ptr mapped at 0x%08lx\n", (unsigned long)info->ringReadPtr); - +#endif if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, DRM_AGP, 0, &info->bufHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -986,7 +1137,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) } xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n", info->ringHandle); - +#if 0 if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, &info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n"); @@ -998,6 +1149,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring contents 0x%08lx\n", *(unsigned long *)(pointer)info->ring); +#endif if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) { @@ -1008,7 +1160,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] ring read ptr handle = 0x%08x\n", info->ringReadPtrHandle); - +#if 0 if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, &info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -1021,6 +1173,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring read ptr contents 0x%08lx\n", *(unsigned long *)(pointer)info->ringReadPtr); +#endif if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) { @@ -1073,6 +1226,9 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) */ static Bool RADEONDRIMapInit(RADEONInfoPtr info, ScreenPtr pScreen) { + + if (info->drm_mm) + return TRUE; /* Map registers */ info->registerSize = info->MMIOSize; if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize, @@ -1094,12 +1250,12 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) memset(&drmInfo, 0, sizeof(drmRadeonInit)); if ( info->ChipFamily >= CHIP_FAMILY_R300 ) - drmInfo.func = DRM_RADEON_INIT_R300_CP; + drmInfo.func = RADEON_INIT_R300_CP; else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) - drmInfo.func = DRM_RADEON_INIT_R200_CP; + drmInfo.func = RADEON_INIT_R200_CP; else - drmInfo.func = DRM_RADEON_INIT_CP; + drmInfo.func = RADEON_INIT_CP; drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); drmInfo.is_pci = (info->cardType!=CARD_AGP); @@ -1111,19 +1267,22 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) drmInfo.fb_bpp = info->CurrentLayout.pixel_code; drmInfo.depth_bpp = (info->depthBits - 8) * 2; - drmInfo.front_offset = info->frontOffset; - drmInfo.front_pitch = info->frontPitch * cpp; - drmInfo.back_offset = info->backOffset; - drmInfo.back_pitch = info->backPitch * cpp; - drmInfo.depth_offset = info->depthOffset; - drmInfo.depth_pitch = info->depthPitch * drmInfo.depth_bpp / 8; - - drmInfo.fb_offset = info->fbHandle; - drmInfo.mmio_offset = info->registerHandle; - drmInfo.ring_offset = info->ringHandle; - drmInfo.ring_rptr_offset = info->ringReadPtrHandle; - drmInfo.buffers_offset = info->bufHandle; - drmInfo.gart_textures_offset= info->gartTexHandle; + if (!info->drm_mm) { + drmInfo.front_offset = info->frontOffset; + drmInfo.front_pitch = info->frontPitch * cpp; + drmInfo.back_offset = info->backOffset; + drmInfo.back_pitch = info->backPitch * cpp; + drmInfo.depth_offset = info->depthOffset; + drmInfo.depth_pitch = info->depthPitch * drmInfo.depth_bpp / 8; + + drmInfo.fb_offset = info->fbHandle; + drmInfo.mmio_offset = info->registerHandle; + drmInfo.ring_offset = info->ringHandle; + drmInfo.ring_rptr_offset = info->ringReadPtrHandle; + drmInfo.buffers_offset = info->bufHandle; + drmInfo.gart_textures_offset= info->gartTexHandle; + } else { + } if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT, &drmInfo, sizeof(drmRadeonInit)) < 0) @@ -1133,7 +1292,8 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) * registers back to their default values, so we need to restore * those engine register here. */ - RADEONEngineRestore(pScrn); + if (!info->drm_mm) + RADEONEngineRestore(pScrn); return TRUE; } @@ -1329,12 +1489,11 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) /* Get DRM version & close DRM */ info->pKernelDRMVersion = drmGetVersion(fd); - drmClose(fd); if (info->pKernelDRMVersion == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] RADEONDRIGetVersion failed to get the DRM version\n" "[dri] Disabling DRI.\n"); - return FALSE; + goto fail; } /* Now check if we qualify */ @@ -1368,10 +1527,29 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) req_patch); drmFreeVersion(info->pKernelDRMVersion); info->pKernelDRMVersion = NULL; - return FALSE; + goto fail; + } + + if (info->pKernelDRMVersion->version_minor >= 30) { + struct drm_radeon_gem_info mminfo; + + if (!drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))) + { + info->drm_mm = TRUE; + info->mm.vram_start = mminfo.vram_start; + info->mm.vram_size = mminfo.vram_size; + info->mm.gart_start = mminfo.vram_start; + info->mm.gart_size = mminfo.gart_size; + ErrorF("initing %llx %llx %llx %llx\n", mminfo.gart_start, + mminfo.gart_size, mminfo.vram_start, mminfo.vram_size); + } } + drmClose(fd); return TRUE; +fail: + drmClose(fd); + return FALSE; } Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) @@ -1380,6 +1558,9 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int value = 0; + if (info->drm_mode_setting) + return TRUE; + if (!info->want_vblank_interrupts) on = FALSE; @@ -1399,6 +1580,48 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) return TRUE; } +Bool RADEONDRIDoMappings(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + /* DRIScreenInit doesn't add all the + * common mappings. Add additional + * mappings here. + */ + + if (info->ChipFamily >= CHIP_FAMILY_R600) + return TRUE; + + if (!RADEONDRIMapInit(info, pScreen)) { + RADEONDRICloseScreen(pScreen); + return FALSE; + } + + radeon_update_sarea(pScrn, pSAREAPriv); + + /* DRIScreenInit adds the frame buffer + map, but we need it as well */ + { + void *scratch_ptr; + int scratch_int; + + DRIGetDeviceInfo(pScreen, &info->fbHandle, + &scratch_int, &scratch_int, + &scratch_int, &scratch_int, + &scratch_ptr); + } + + /* FIXME: When are these mappings unmapped? */ + + if (!RADEONInitVisualConfigs(pScreen)) { + RADEONDRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n"); + return TRUE; + +} /* Initialize the screen-specific data structures for the DRI and the * Radeon. This is the main entry point to the device-specific @@ -1462,10 +1685,23 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo->ddxDriverMajorVersion = info->allowColorTiling ? 5 : 4; pDRIInfo->ddxDriverMinorVersion = 3; pDRIInfo->ddxDriverPatchVersion = 0; - pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->frontOffset; - pDRIInfo->frameBufferSize = info->FbMapSize - info->FbSecureSize; - pDRIInfo->frameBufferStride = (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes); + +#if DRI_DRIVER_FRAMEBUFFER_MAP + /* only map the fb ourselves if we have the memory manager in place */ + if (info->drm_mm) { + pDRIInfo->frameBufferPhysicalAddress = 0; + pDRIInfo->frameBufferSize = 0; + pDRIInfo->frameBufferStride = 0; + pDRIInfo->dontMapFrameBuffer = TRUE; + } else +#endif + { + pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->frontOffset; + pDRIInfo->frameBufferSize = info->FbMapSize - info->FbSecureSize; + pDRIInfo->frameBufferStride = (pScrn->displayWidth * + info->CurrentLayout.pixel_bytes); + } + pDRIInfo->ddxDrawableTableEntry = RADEON_MAX_DRAWABLES; pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES < RADEON_MAX_DRAWABLES @@ -1518,9 +1754,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d; pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d; pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d; -#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ - (DRIINFO_MAJOR_VERSION == 5 && \ - DRIINFO_MINOR_VERSION >= 1)) +#if DRI_SUPPORT_CLIP_NOTIFY pDRIInfo->ClipNotify = RADEONDRIClipNotify; #endif @@ -1552,57 +1786,61 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo = NULL; return FALSE; } - /* Initialize AGP */ - if (info->cardType==CARD_AGP && !RADEONDRIAgpInit(info, pScreen)) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[agp] AGP failed to initialize. Disabling the DRI.\n" ); - xf86DrvMsg(pScreen->myNum, X_INFO, - "[agp] You may want to make sure the agpgart kernel " - "module\nis loaded before the radeon kernel module.\n"); - RADEONDRICloseScreen(pScreen); - return FALSE; - } - - /* Initialize PCI */ - if ((info->cardType!=CARD_AGP) && !RADEONDRIPciInit(info, pScreen)) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[pci] PCI failed to initialize. Disabling the DRI.\n" ); - RADEONDRICloseScreen(pScreen); - return FALSE; - } - - /* DRIScreenInit doesn't add all the - * common mappings. Add additional - * mappings here. - */ - if (!RADEONDRIMapInit(info, pScreen)) { - RADEONDRICloseScreen(pScreen); - return FALSE; - } - /* DRIScreenInit adds the frame buffer - map, but we need it as well */ - { - void *scratch_ptr; - int scratch_int; + /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */ + if (pDRIInfo->frameBufferSize != 0 && info->drm_mm) { + int tmp; + drm_handle_t fb_handle; + void *ptmp; - DRIGetDeviceInfo(pScreen, &info->fbHandle, - &scratch_int, &scratch_int, - &scratch_int, &scratch_int, - &scratch_ptr); + /* With the compat method, it will continue to report + * the wrong map out of GetDeviceInfo, which will break AIGLX. + */ + DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp); + drmRmMap(info->drmFD, fb_handle); + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Removed DRI frontbuffer mapping in compatibility mode.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRIGetDeviceInfo will report incorrect frontbuffer " + "handle.\n"); + } + + if (info->drm_mm) { + int ret; + ret = radeon_dri_gart_init(pScreen); + if (!ret) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[gart] GART failed to initialize. Disabling the DRI.\n" ); + RADEONDRICloseScreen(pScreen); + return FALSE; + } + } else { + if (info->cardType==CARD_AGP && !RADEONDRIAgpInit(info, pScreen)) { + /* Initialize AGP */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] AGP failed to initialize. Disabling the DRI.\n" ); + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] You may want to make sure the agpgart kernel " + "module\nis loaded before the radeon kernel module.\n"); + RADEONDRICloseScreen(pScreen); + return FALSE; + } + + /* Initialize PCI */ + if ((info->cardType!=CARD_AGP) && !RADEONDRIPciInit(info, pScreen)) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[pci] PCI failed to initialize. Disabling the DRI.\n" ); + RADEONDRICloseScreen(pScreen); + return FALSE; + } } - /* FIXME: When are these mappings unmapped? */ - - if (!RADEONInitVisualConfigs(pScreen)) { - RADEONDRICloseScreen(pScreen); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n"); return TRUE; } + static Bool RADEONDRIDoCloseScreen(int scrnIndex, ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1644,14 +1882,18 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) return FALSE; } - /* Initialize the vertex buffers list */ - if (!RADEONDRIBufInit(info, pScreen)) { - RADEONDRICloseScreen(pScreen); - return FALSE; + if (!info->drm_mm) { + /* Initialize the vertex buffers list */ + if (!RADEONDRIBufInit(info, pScreen)) { + RADEONDRICloseScreen(pScreen); + return FALSE; + } } - /* Initialize IRQ */ - RADEONDRIIrqInit(info, pScreen); + if (!info->drm_mode_setting) { + /* Initialize IRQ */ + RADEONDRIIrqInit(info, pScreen); + } /* Initialize kernel GART memory manager */ RADEONDRIGartHeapInit(info, pScreen); @@ -1663,6 +1905,10 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) pSAREAPriv = (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScreen); memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); + if (info->drm_mm) { + /* init the handles into the sarea */ + + } pRADEONDRI = (RADEONDRIPtr)info->pDRIInfo->devPrivate; pRADEONDRI->deviceID = info->Chipset; @@ -1806,7 +2052,7 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) /* De-allocate all kernel resources */ memset(&drmInfo, 0, sizeof(drmRadeonInit)); - drmInfo.func = DRM_RADEON_CLEANUP_CP; + drmInfo.func = RADEON_CLEANUP_CP; drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT, &drmInfo, sizeof(drmRadeonInit)); @@ -1819,6 +2065,7 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) drmUnmap(info->buf, info->bufMapSize); info->buf = NULL; } +#if 0 if (info->ringReadPtr) { drmUnmap(info->ringReadPtr, info->ringReadMapSize); info->ringReadPtr = NULL; @@ -1827,6 +2074,7 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) drmUnmap(info->ring, info->ringMapSize); info->ring = NULL; } +#endif if (info->agpMemHandle != DRM_AGP_NO_HANDLE) { drmAgpUnbind(info->drmFD, info->agpMemHandle); drmAgpFree(info->drmFD, info->agpMemHandle); @@ -1903,7 +2151,7 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg) /* Don't want to do this when no 3d is active and pages are * right-way-round */ - if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) + if (!pSAREAPriv->pfState && pSAREAPriv->pfCurrentPage == 0) return; REGION_NULL(pScreen, ®ion); @@ -1992,7 +2240,7 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) .y2 = pScrn->virtualY - 1 }; RegionPtr pReg = REGION_CREATE(pScreen, &box, 1); - pSAREAPriv->pfAllowPageFlip = 1; + pSAREAPriv->pfState = 1; RADEONDRIRefreshArea(pScrn, pReg); REGION_DESTROY(pScreen, pReg); } @@ -2007,7 +2255,7 @@ static void RADEONDisablePageFlip(ScreenPtr pScreen) */ RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); - pSAREAPriv->pfAllowPageFlip = 0; + pSAREAPriv->pfState = 0; } static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen) @@ -2232,3 +2480,16 @@ int RADEONDRISetParam(ScrnInfoPtr pScrn, unsigned int param, int64_t value) &radeonsetparam, sizeof(drmRadeonSetParam)); return ret; } + +static Bool radeon_dri_gart_init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONDRIInitGARTValues(info); + + /* so we want to allocate the buffers/gart texmap */ + /* ignore ring stuff */ + return radeon_setup_gart_mem(pScreen); + +} diff --git a/src/radeon_dri_bufmgr.c b/src/radeon_dri_bufmgr.c new file mode 100644 index 0000000..37cc305 --- /dev/null +++ b/src/radeon_dri_bufmgr.c @@ -0,0 +1,159 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#include +#include +#include +#include "radeon_dri_bufmgr.h" + +/** @file dri_bufmgr.c + * + * Convenience functions for buffer management methods. + */ + +dri_bo * +dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, + unsigned int alignment, uint64_t location_mask) +{ + return bufmgr->bo_alloc(bufmgr, name, size, alignment, location_mask); +} + +dri_bo * +dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name, unsigned long offset, + unsigned long size, void *virtual, + uint64_t location_mask) +{ + return bufmgr->bo_alloc_static(bufmgr, name, offset, size, virtual, + location_mask); +} + +void +dri_bo_reference(dri_bo *bo) +{ + bo->bufmgr->bo_reference(bo); +} + +void +dri_bo_unreference(dri_bo *bo) +{ + if (bo == NULL) + return; + + bo->bufmgr->bo_unreference(bo); +} + +int +dri_bo_map(dri_bo *buf, int write_enable) +{ + return buf->bufmgr->bo_map(buf, write_enable); +} + +int +dri_bo_unmap(dri_bo *buf) +{ + return buf->bufmgr->bo_unmap(buf); +} + +void +dri_fence_wait(dri_fence *fence) +{ + fence->bufmgr->fence_wait(fence); +} + +void +dri_fence_reference(dri_fence *fence) +{ + fence->bufmgr->fence_reference(fence); +} + +void +dri_fence_unreference(dri_fence *fence) +{ + if (fence == NULL) + return; + + fence->bufmgr->fence_unreference(fence); +} + +void +dri_bo_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, const void *data) +{ + if (size == 0 || data == NULL) + return; + + dri_bo_map(bo, 1); + memcpy((unsigned char *)bo->virtual + offset, data, size); + dri_bo_unmap(bo); +} + +void +dri_bo_get_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, void *data) +{ + if (size == 0 || data == NULL) + return; + + dri_bo_map(bo, 0); + memcpy(data, (unsigned char *)bo->virtual + offset, size); + dri_bo_unmap(bo); +} + +void +dri_bufmgr_destroy(dri_bufmgr *bufmgr) +{ + bufmgr->destroy(bufmgr); +} + + +int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, uint32_t delta, + uint32_t offset, dri_bo *target_buf) +{ + return reloc_buf->bufmgr->emit_reloc(reloc_buf, flags, delta, offset, target_buf); +} + +void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count) +{ + return batch_buf->bufmgr->process_relocs(batch_buf, count); +} + +void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence) +{ + batch_buf->bufmgr->post_submit(batch_buf, last_fence); +} + +void +dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug) +{ + bufmgr->debug = enable_debug; +} + +int +dri_bufmgr_check_aperture_space(dri_bo *bo) +{ + return bo->bufmgr->check_aperture_space(bo); +} diff --git a/src/radeon_dri_bufmgr.h b/src/radeon_dri_bufmgr.h new file mode 100644 index 0000000..687cbeb --- /dev/null +++ b/src/radeon_dri_bufmgr.h @@ -0,0 +1,260 @@ +/************************************************************************** + * + * Copyright © 2007 Intel Corporation + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ +/* + * Authors: Thomas Hellström + * Keith Whitwell + * Eric Anholt + */ + +#ifndef _DRI_BUFMGR_H_ +#define _DRI_BUFMGR_H_ +#include + +typedef struct _dri_bufmgr dri_bufmgr; +typedef struct _dri_bo dri_bo; +typedef struct _dri_fence dri_fence; + +struct _dri_bo { + /** Size in bytes of the buffer object. */ + unsigned long size; + /** + * Card virtual address (offset from the beginning of the aperture) for the + * object. Only valid while validated. + */ + unsigned long offset; + /** + * Virtual address for accessing the buffer data. Only valid while mapped. + */ + void *virtual; + /** Buffer manager context associated with this buffer object */ + dri_bufmgr *bufmgr; +}; + +struct _dri_fence { + /** + * This is an ORed mask of DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE, and + * DRM_FLAG_EXE indicating the operations associated with this fence. + * + * It is constant for the life of the fence object. + */ + unsigned int type; + /** Buffer manager context associated with this fence */ + dri_bufmgr *bufmgr; +}; + +/** + * Context for a buffer manager instance. + * + * Contains public methods followed by private storage for the buffer manager. + */ +struct _dri_bufmgr { + /** + * Allocate a buffer object. + * + * Buffer objects are not necessarily initially mapped into CPU virtual + * address space or graphics device aperture. They must be mapped using + * bo_map() to be used by the CPU, and validated for use using bo_validate() + * to be used from the graphics device. + */ + dri_bo *(*bo_alloc)(dri_bufmgr *bufmgr_ctx, const char *name, + unsigned long size, unsigned int alignment, + uint64_t location_mask); + + /** + * Allocates a buffer object for a static allocation. + * + * Static allocations are ones such as the front buffer that are offered by + * the X Server, which are never evicted and never moved. + */ + dri_bo *(*bo_alloc_static)(dri_bufmgr *bufmgr_ctx, const char *name, + unsigned long offset, unsigned long size, + void *virtual, uint64_t location_mask); + + /** Takes a reference on a buffer object */ + void (*bo_reference)(dri_bo *bo); + + /** + * Releases a reference on a buffer object, freeing the data if + * rerefences remain. + */ + void (*bo_unreference)(dri_bo *bo); + + /** + * Maps the buffer into userspace. + * + * This function will block waiting for any existing fence on the buffer to + * clear, first. The resulting mapping is available at buf->virtual. +\ */ + int (*bo_map)(dri_bo *buf, int write_enable); + + /** Reduces the refcount on the userspace mapping of the buffer object. */ + int (*bo_unmap)(dri_bo *buf); + + /** Takes a reference on a fence object */ + void (*fence_reference)(dri_fence *fence); + + /** + * Releases a reference on a fence object, freeing the data if + * rerefences remain. + */ + void (*fence_unreference)(dri_fence *fence); + + /** + * Blocks until the given fence is signaled. + */ + void (*fence_wait)(dri_fence *fence); + + /** + * Tears down the buffer manager instance. + */ + void (*destroy)(dri_bufmgr *bufmgr); + + /** + * Add relocation entry in reloc_buf, which will be updated with the + * target buffer's real offset on on command submission. + * + * Relocations remain in place for the lifetime of the buffer object. + * + * \param reloc_buf Buffer to write the relocation into. + * \param flags BO flags to be used in validating the target buffer. + * Applicable flags include: + * - DRM_BO_FLAG_READ: The buffer will be read in the process of + * command execution. + * - DRM_BO_FLAG_WRITE: The buffer will be written in the process of + * command execution. + * - DRM_BO_FLAG_MEM_TT: The buffer should be validated in TT memory. + * - DRM_BO_FLAG_MEM_VRAM: The buffer should be validated in video + * memory. + * \param delta Constant value to be added to the relocation target's offset. + * \param offset Byte offset within batch_buf of the relocated pointer. + * \param target Buffer whose offset should be written into the relocation + * entry. + */ + int (*emit_reloc)(dri_bo *reloc_buf, uint64_t flags, uint32_t delta, + uint32_t offset, dri_bo *target); + + /** + * Processes the relocations, either in userland or by converting the list + * for use in batchbuffer submission. + * + * Kernel-based implementations will return a pointer to the arguments + * to be handed with batchbuffer submission to the kernel. The userland + * implementation performs the buffer validation and emits relocations + * into them the appopriate order. + * + * \param batch_buf buffer at the root of the tree of relocations + * \param count returns the number of buffers validated. + * \return relocation record for use in command submission. + * */ + void *(*process_relocs)(dri_bo *batch_buf, uint32_t *count); + + void (*post_submit)(dri_bo *batch_buf, dri_fence **fence); + + int (*check_aperture_space)(dri_bo *bo); + int debug; /**< Enables verbose debugging printouts */ +}; + +dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size, + unsigned int alignment, uint64_t location_mask); +dri_bo *dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name, + unsigned long offset, unsigned long size, + void *virtual, uint64_t location_mask); +void dri_bo_reference(dri_bo *bo); +void dri_bo_unreference(dri_bo *bo); +int dri_bo_map(dri_bo *buf, int write_enable); +int dri_bo_unmap(dri_bo *buf); +void dri_fence_wait(dri_fence *fence); +void dri_fence_reference(dri_fence *fence); +void dri_fence_unreference(dri_fence *fence); + +void dri_bo_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, const void *data); +void dri_bo_get_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, void *data); + +void dri_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); +dri_bufmgr *dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual, + unsigned long size, + unsigned int (*fence_emit)(void *private), + int (*fence_wait)(void *private, + unsigned int cookie), + void *driver_priv); +void dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug); +void dri_bo_fake_disable_backing_store(dri_bo *bo, + void (*invalidate_cb)(dri_bo *bo, + void *ptr), + void *ptr); +void dri_bufmgr_destroy(dri_bufmgr *bufmgr); + +int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, uint32_t delta, + uint32_t offset, dri_bo *target_buf); +void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count); +void dri_post_process_relocs(dri_bo *batch_buf); +void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence); +int dri_bufmgr_check_aperture_space(dri_bo *bo); + +#ifndef TTM_API +/* reuse some TTM API */ + +#define DRM_BO_MEM_LOCAL 0 +#define DRM_BO_MEM_TT 1 +#define DRM_BO_MEM_VRAM 2 +#define DRM_BO_MEM_PRIV0 3 +#define DRM_BO_MEM_PRIV1 4 +#define DRM_BO_MEM_PRIV2 5 +#define DRM_BO_MEM_PRIV3 6 +#define DRM_BO_MEM_PRIV4 7 + +#define DRM_BO_FLAG_READ (1ULL << 0) +#define DRM_BO_FLAG_WRITE (1ULL << 1) +#define DRM_BO_FLAG_EXE (1ULL << 2) +#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE) +#define DRM_BO_FLAG_NO_EVICT (1ULL << 4) + +#define DRM_BO_FLAG_MAPPABLE (1ULL << 5) +#define DRM_BO_FLAG_SHAREABLE (1ULL << 6) + +#define DRM_BO_FLAG_CACHED (1ULL << 7) + +#define DRM_BO_FLAG_NO_MOVE (1ULL << 8) +#define DRM_BO_FLAG_CACHED_MAPPED (1ULL << 19) +#define DRM_BO_FLAG_FORCE_CACHING (1ULL << 13) +#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14) +#define DRM_BO_FLAG_TILE (1ULL << 15) + +#define DRM_BO_FLAG_MEM_LOCAL (1ULL << 24) +#define DRM_BO_FLAG_MEM_TT (1ULL << 25) +#define DRM_BO_FLAG_MEM_VRAM (1ULL << 26) + +#define DRM_BO_MASK_MEM 0x00000000FF000000ULL + +#define DRM_FENCE_TYPE_EXE 0x00000001 +#endif + +#endif diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 45d2c2f..d5bb24d 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -224,7 +224,10 @@ radeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; *size = stride; - return ((uint8_t *)info->FB + row * stride + offset); + if (info->drm_mm) + return ((uint8_t *)info->mm.front_buffer->map + row * stride + offset); + else + return ((uint8_t *)info->FB + row * stride + offset); } static Bool RADEONCreateScreenResources (ScreenPtr pScreen) @@ -1621,6 +1624,7 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) } pScrn->videoRam &= ~1023; + info->FbMapSize = pScrn->videoRam * 1024; /* if the card is PCI Express reserve the last 32k for the gart table */ @@ -1748,56 +1752,62 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) from = X_PROBED; info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffUL; pScrn->memPhysBase = info->LinearAddr; - if (dev->MemBase) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Linear address override, using 0x%016lx instead of 0x%016lx\n", - dev->MemBase, - info->LinearAddr); - info->LinearAddr = dev->MemBase; - from = X_CONFIG; - } else if (!info->LinearAddr) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid linear framebuffer address\n"); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, from, - "Linear framebuffer at 0x%016lx\n", info->LinearAddr); -#ifndef XSERVER_LIBPCIACCESS - /* BIOS */ - from = X_PROBED; - info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; - if (dev->BiosBase) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS address override, using 0x%08lx instead of 0x%08lx\n", - dev->BiosBase, - info->BIOSAddr); - info->BIOSAddr = dev->BiosBase; - from = X_CONFIG; - } - if (info->BIOSAddr) { + if (!info->drm_mode_setting) { + from = X_PROBED; + info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffUL; + pScrn->memPhysBase = info->LinearAddr; + if (dev->MemBase) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Linear address override, using 0x%016lx instead of 0x%016lx\n", + dev->MemBase, + info->LinearAddr); + info->LinearAddr = dev->MemBase; + from = X_CONFIG; + } else if (!info->LinearAddr) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid linear framebuffer address\n"); + return FALSE; + } xf86DrvMsg(pScrn->scrnIndex, from, - "BIOS at 0x%08lx\n", info->BIOSAddr); - } + "Linear framebuffer at 0x%016lx\n", info->LinearAddr); + +#ifndef XSERVER_LIBPCIACCESS + /* BIOS */ + from = X_PROBED; + info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; + if (dev->BiosBase) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS address override, using 0x%08lx instead of 0x%08lx\n", + dev->BiosBase, + info->BIOSAddr); + info->BIOSAddr = dev->BiosBase; + from = X_CONFIG; + } + if (info->BIOSAddr) { + xf86DrvMsg(pScrn->scrnIndex, from, + "BIOS at 0x%08lx\n", info->BIOSAddr); + } #endif - /* Read registers used to determine options */ - /* Check chip errata */ - info->ChipErrata = 0; + /* Read registers used to determine options */ + /* Check chip errata */ + info->ChipErrata = 0; - if (info->ChipFamily == CHIP_FAMILY_R300 && - (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) - == RADEON_CFG_ATI_REV_A11) + if (info->ChipFamily == CHIP_FAMILY_R300 && + (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) + == RADEON_CFG_ATI_REV_A11) info->ChipErrata |= CHIP_ERRATA_R300_CG; - - if (info->ChipFamily == CHIP_FAMILY_RV200 || - info->ChipFamily == CHIP_FAMILY_RS200) + + if (info->ChipFamily == CHIP_FAMILY_RV200 || + info->ChipFamily == CHIP_FAMILY_RS200) info->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS; - - if (info->ChipFamily == CHIP_FAMILY_RV100 || - info->ChipFamily == CHIP_FAMILY_RS100 || - info->ChipFamily == CHIP_FAMILY_RS200) + + if (info->ChipFamily == CHIP_FAMILY_RV100 || + info->ChipFamily == CHIP_FAMILY_RS100 || + info->ChipFamily == CHIP_FAMILY_RS200) info->ChipErrata |= CHIP_ERRATA_PLL_DELAY; + } #ifdef XF86DRI /* AGP/PCI */ @@ -1985,6 +1995,9 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { int errmaj = 0, errmin = 0; +#if defined(USE_EXA) + info->useEXA = TRUE; +#endif from = X_DEFAULT; #if defined(USE_EXA) #if defined(USE_XAA) @@ -1995,6 +2008,7 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) info->useEXA = TRUE; } else if (xf86NameCmp(optstr, "XAA") == 0) { from = X_CONFIG; + info->useEXA = FALSE; } } #else /* USE_XAA */ @@ -2664,6 +2678,37 @@ static const xf86CrtcConfigFuncsRec RADEONCRTCResizeFuncs = { RADEONCRTCResize }; +#ifdef XF86DRM_MODE +static Bool radeon_kernel_mode_enabled(ScrnInfoPtr pScrn) +{ +#if XSERVER_LIBPCIACCESS + struct pci_device *PciInfo; +#else + pciVideoPtr PciInfo; +#endif + EntityInfoPtr pEnt; + char *busIdString; + int ret; + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + PciInfo = xf86GetPciInfoForEntity(pEnt->index); + + if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) + return FALSE; + + busIdString = DRICreatePCIBusID(PciInfo); + ret = drmCheckModesettingSupported(busIdString); + xfree(busIdString); + if (ret) + return FALSE; + + return TRUE; +} +#else +#define radeon_kernel_mode_enabled(x) FALSE +#endif + + Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) { xf86CrtcConfigPtr xf86_config; @@ -2684,6 +2729,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info = RADEONPTR(pScrn); info->MMIO = NULL; + info->drm_mode_setting = radeon_kernel_mode_enabled(pScrn); + info->IsSecondary = FALSE; info->IsPrimary = FALSE; @@ -2718,59 +2765,63 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) } info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); - info->PciTag = pciTag(PCI_DEV_BUS(info->PciInfo), - PCI_DEV_DEV(info->PciInfo), - PCI_DEV_FUNC(info->PciInfo)); - info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & ~0xffUL; - info->MMIOSize = PCI_REGION_SIZE(info->PciInfo, 2); - if (info->pEnt->device->IOBase) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "MMIO address override, using 0x%08lx instead of 0x%08lx\n", - info->pEnt->device->IOBase, - info->MMIOAddr); - info->MMIOAddr = info->pEnt->device->IOBase; - } else if (!info->MMIOAddr) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); - goto fail1; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MMIO registers at 0x%016lx: size %ldKB\n", info->MMIOAddr, info->MMIOSize / 1024); - if(!RADEONMapMMIO(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Memory map the MMIO region failed\n"); - goto fail1; - } + if (!info->drm_mode_setting) { + info->PciTag = pciTag(PCI_DEV_BUS(info->PciInfo), + PCI_DEV_DEV(info->PciInfo), + PCI_DEV_FUNC(info->PciInfo)); + info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & ~0xffUL; + info->MMIOSize = PCI_REGION_SIZE(info->PciInfo, 2); + if (info->pEnt->device->IOBase) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MMIO address override, using 0x%08lx instead of 0x%08lx\n", + info->pEnt->device->IOBase, + info->MMIOAddr); + info->MMIOAddr = info->pEnt->device->IOBase; + } else if (!info->MMIOAddr) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); + goto fail1; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MMIO registers at 0x%016lx: size %ldKB\n", info->MMIOAddr, info->MMIOSize / 1024); + + if(!RADEONMapMMIO(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Memory map the MMIO region failed\n"); + goto fail1; + } + #if !defined(__alpha__) - if ( + if ( #ifndef XSERVER_LIBPCIACCESS - xf86GetPciDomain(info->PciTag) || + xf86GetPciDomain(info->PciTag) || #endif - !xf86IsPrimaryPci(info->PciInfo)) - RADEONPreInt10Save(pScrn, &int10_save); + !xf86IsPrimaryPci(info->PciInfo)) + RADEONPreInt10Save(pScrn, &int10_save); #else - /* [Alpha] On the primary, the console already ran the BIOS and we're - * going to run it again - so make sure to "fix up" the card - * so that (1) we can read the BIOS ROM and (2) the BIOS will - * get the memory config right. - */ - RADEONPreInt10Save(pScrn, &int10_save); + /* [Alpha] On the primary, the console already ran the BIOS and we're + * going to run it again - so make sure to "fix up" the card + * so that (1) we can read the BIOS ROM and (2) the BIOS will + * get the memory config right. + */ + RADEONPreInt10Save(pScrn, &int10_save); #endif - - if (flags & PROBE_DETECT) { - RADEONProbeDDC(pScrn, info->pEnt->index); - RADEONPostInt10Check(pScrn, int10_save); - if(info->MMIO) RADEONUnmapMMIO(pScrn); - return TRUE; - } + + if (flags & PROBE_DETECT) { + RADEONProbeDDC(pScrn, info->pEnt->index); + RADEONPostInt10Check(pScrn, int10_save); + if(info->MMIO) RADEONUnmapMMIO(pScrn); + return TRUE; + } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "PCI bus %d card %d func %d\n", - PCI_DEV_BUS(info->PciInfo), - PCI_DEV_DEV(info->PciInfo), - PCI_DEV_FUNC(info->PciInfo)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PCI bus %d card %d func %d\n", + PCI_DEV_BUS(info->PciInfo), + PCI_DEV_DEV(info->PciInfo), + PCI_DEV_FUNC(info->PciInfo)); + } if (xf86RegisterResources(info->pEnt->index, 0, ResExclusive)) goto fail; @@ -2780,10 +2831,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; pScrn->monitor = pScrn->confScreen->monitor; - /* Allocate an xf86CrtcConfig */ - xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs); - xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - + if (!info->drm_mode_setting) { + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + } if (!RADEONPreInitVisual(pScrn)) goto fail; @@ -2797,136 +2850,194 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) memcpy(info->Options, RADEONOptions, sizeof(RADEONOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); - /* By default, don't do VGA IOs on ppc/sparc */ + if (!info->drm_mode_setting) { + /* By default, don't do VGA IOs on ppc/sparc */ #if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW) - info->VGAAccess = FALSE; + info->VGAAccess = FALSE; #else - info->VGAAccess = TRUE; + info->VGAAccess = TRUE; #endif - + #ifdef WITH_VGAHW - xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess); - if (info->VGAAccess) { - if (!xf86LoadSubModule(pScrn, "vgahw")) - info->VGAAccess = FALSE; - else { - if (!vgaHWGetHWRec(pScrn)) - info->VGAAccess = FALSE; - } - if (!info->VGAAccess) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed," - " trying to run without it\n"); - } else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE," - " VGA module load skipped\n"); - if (info->VGAAccess) - vgaHWGetIOBase(VGAHWPTR(pScrn)); + xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess); + if (info->VGAAccess) { + if (!xf86LoadSubModule(pScrn, "vgahw")) + info->VGAAccess = FALSE; + else { + if (!vgaHWGetHWRec(pScrn)) + info->VGAAccess = FALSE; + } + if (!info->VGAAccess) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed," + " trying to run without it\n"); + } else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE," + " VGA module load skipped\n"); + if (info->VGAAccess) + vgaHWGetIOBase(VGAHWPTR(pScrn)); #endif - - + + } + if (!RADEONPreInitWeight(pScrn)) goto fail; - info->DispPriority = 1; - if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) { - if (strcmp(s, "AUTO") == 0) { - info->DispPriority = 1; - } else if (strcmp(s, "BIOS") == 0) { - info->DispPriority = 0; - } else if (strcmp(s, "HIGH") == 0) { - info->DispPriority = 2; - } else - info->DispPriority = 1; - } - if (!RADEONPreInitChipType(pScrn)) - goto fail; - - if (!RADEONPreInitInt10(pScrn, &pInt10)) - goto fail; - - RADEONPostInt10Check(pScrn, int10_save); - - if (!RADEONPreInitBIOS(pScrn, pInt10)) - goto fail; + goto fail; + + if (!info->drm_mode_setting) { + info->DispPriority = 1; + if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) { + if (strcmp(s, "AUTO") == 0) { + info->DispPriority = 1; + } else if (strcmp(s, "BIOS") == 0) { + info->DispPriority = 0; + } else if (strcmp(s, "HIGH") == 0) { + info->DispPriority = 2; + } else + info->DispPriority = 1; + } + + + if (!RADEONPreInitInt10(pScrn, &pInt10)) + goto fail; + + RADEONPostInt10Check(pScrn, int10_save); + if (!RADEONPreInitBIOS(pScrn, pInt10)) + goto fail; #ifdef XF86DRI - /* PreInit DRI first of all since we need that for getting a proper - * memory map - */ - info->directRenderingEnabled = RADEONPreInitDRI(pScrn); + /* PreInit DRI first of all since we need that for getting a proper + * memory map + */ + info->directRenderingEnabled = RADEONPreInitDRI(pScrn); #endif - if (!RADEONPreInitVRAM(pScrn)) - goto fail; - - RADEONPreInitColorTiling(pScrn); - - /* we really need an FB manager... */ - if (pScrn->display->virtualX) { - crtc_max_X = pScrn->display->virtualX; - crtc_max_Y = pScrn->display->virtualY; - if (info->allowColorTiling) { - if (crtc_max_X > info->MaxSurfaceWidth || - crtc_max_Y > info->MaxLines) { - info->allowColorTiling = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Requested desktop size exceeds surface limts for tiling, ColorTiling disabled\n"); + + if (!RADEONPreInitVRAM(pScrn)) + goto fail; + + RADEONPreInitColorTiling(pScrn); + + /* we really need an FB manager... */ + if (pScrn->display->virtualX) { + crtc_max_X = pScrn->display->virtualX; + crtc_max_Y = pScrn->display->virtualY; + if (info->allowColorTiling) { + if (crtc_max_X > info->MaxSurfaceWidth || + crtc_max_Y > info->MaxLines) { + info->allowColorTiling = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Requested desktop size exceeds surface limts for tiling, ColorTiling disabled\n"); + } } - } - if (crtc_max_X > 8192) - crtc_max_X = 8192; - if (crtc_max_Y > 8192) - crtc_max_Y = 8192; - } else { - /* - * note that these aren't really the CRTC limits, they're just - * heuristics until we have a better memory manager. - */ - if (pScrn->videoRam <= 16384) { - crtc_max_X = 1600; - crtc_max_Y = 1200; - } else if (IS_R300_VARIANT) { - crtc_max_X = 2560; - crtc_max_Y = 1200; - } else if (IS_AVIVO_VARIANT) { - crtc_max_X = 2560; - crtc_max_Y = 1600; + if (crtc_max_X > 8192) + crtc_max_X = 8192; + if (crtc_max_Y > 8192) + crtc_max_Y = 8192; } else { - crtc_max_X = 2048; - crtc_max_Y = 1200; + /* + * note that these aren't really the CRTC limits, they're just + * heuristics until we have a better memory manager. + */ + if (pScrn->videoRam <= 16384) { + crtc_max_X = 1600; + crtc_max_Y = 1200; + } else if (IS_R300_VARIANT) { + crtc_max_X = 2560; + crtc_max_Y = 1200; + } else if (IS_AVIVO_VARIANT) { + crtc_max_X = 2560; + crtc_max_Y = 1600; + } else { + crtc_max_X = 2048; + crtc_max_Y = 1200; } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n", - crtc_max_X, crtc_max_Y); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "If you are having trouble with 3D, " - "reduce the desktop size by adjusting the Virtual line to your xorg.conf\n"); - + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n", + crtc_max_X, crtc_max_Y); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "If you are having trouble with 3D, " + "reduce the desktop size by adjusting the Virtual line to your xorg.conf\n"); + /*xf86CrtcSetSizeRange (pScrn, 320, 200, info->MaxSurfaceWidth, info->MaxLines);*/ - xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y); + xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y); + + RADEONPreInitDDC(pScrn); - RADEONPreInitDDC(pScrn); + if (!RADEONPreInitControllers(pScrn)) + goto fail; - if (!RADEONPreInitControllers(pScrn)) - goto fail; + ErrorF("before xf86InitialConfiguration\n"); + + if (!xf86InitialConfiguration (pScrn, FALSE)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + goto fail; + } + + ErrorF("after xf86InitialConfiguration\n"); + + } else { +#ifdef XF86DRM_MODE + char *bus_id; + bus_id = DRICreatePCIBusID(info->PciInfo); + if (drmmode_pre_init(pScrn, &info->drmmode, bus_id, "radeon", pScrn->bitsPerPixel / 8) == FALSE) { + xfree(bus_id); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n"); + goto fail; + } - ErrorF("before xf86InitialConfiguration\n"); + info->drmmode.create_new_fb = radeon_create_new_fb; + info->drmFD = info->drmmode.fd; + xfree(bus_id); + + { + struct drm_radeon_gem_info mminfo; + + if (!drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))) + { + info->mm.vram_start = mminfo.vram_start; + info->mm.vram_size = mminfo.vram_visible; + info->mm.gart_start = mminfo.gart_start; + info->mm.gart_size = mminfo.gart_size; + ErrorF("initing %llx %llx %llx %llx %llx\n", mminfo.gart_start, + mminfo.gart_size, mminfo.vram_start, mminfo.vram_size, mminfo.vram_visible); + } + { + drmRadeonGetParam gp; + int value; - if (!xf86InitialConfiguration (pScrn, FALSE)) - { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); - goto fail; - } + memset(&gp, 0, sizeof(gp)); + gp.param = RADEON_PARAM_FB_LOCATION; + gp.value = &value; - ErrorF("after xf86InitialConfiguration\n"); + if (drmCommandWriteRead(info->drmFD, DRM_RADEON_GETPARAM, &gp, + sizeof(gp)) < 0) { + goto fail; + } + if (info->ChipFamily >= CHIP_FAMILY_R600) + info->fbLocation = (value & 0xffff) << 24; + else + info->fbLocation = (value & 0xffff) << 16; + } + } + if (info->ChipFamily < CHIP_FAMILY_R600) { + info->useEXA = TRUE; + info->directRenderingEnabled = TRUE; + } + info->new_cs = TRUE; + info->drm_mm = TRUE; + // info->directRenderingDisabled = FALSE; +#endif + } RADEONSetPitch(pScrn); - /* Set display resolution */ - xf86SetDpi(pScrn, 0, 0); + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); /* Get ScreenInit function */ if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; @@ -2941,10 +3052,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONPreInitXv(pScrn)) goto fail; } - if (!xf86RandR12PreInit (pScrn)) - { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); - goto fail; + if (!info->drm_mode_setting) { + if (!xf86RandR12PreInit (pScrn)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); + goto fail; + } } if (pScrn->modes == NULL) { @@ -3185,7 +3298,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int subPixelOrder = SubPixelUnknown; char* s; #endif - + void *front_ptr; info->accelOn = FALSE; #ifdef USE_XAA @@ -3205,52 +3318,55 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, "RADEONScreenInit %lx %ld\n", pScrn->memPhysBase, pScrn->fbOffset); #endif - if (!RADEONMapMem(pScrn)) return FALSE; + + if (!info->drm_mode_setting) { + if (!RADEONMapMem(pScrn)) return FALSE; #ifdef XF86DRI - info->fbX = 0; - info->fbY = 0; + info->fbX = 0; + info->fbY = 0; #endif + + info->PaletteSavedOnVT = FALSE; - info->PaletteSavedOnVT = FALSE; + info->crtc_on = FALSE; + info->crtc2_on = FALSE; - info->crtc_on = FALSE; - info->crtc2_on = FALSE; + RADEONSave(pScrn); - RADEONSave(pScrn); + /* set initial bios scratch reg state */ + RADEONInitBIOSRegisters(pScrn); - /* set initial bios scratch reg state */ - RADEONInitBIOSRegisters(pScrn); + /* blank the outputs/crtcs */ + RADEONBlank(pScrn); - /* blank the outputs/crtcs */ - RADEONBlank(pScrn); + if (info->IsMobility && !IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + RADEONSetDynamicClock(pScrn, 1); + } else { + RADEONSetDynamicClock(pScrn, 0); + } + } else if (IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + atombios_static_pwrmgt_setup(pScrn, 1); + atombios_dyn_clk_setup(pScrn, 1); + } + } + + if (IS_R300_VARIANT || IS_RV100_VARIANT) + RADEONForceSomeClocks(pScrn); - if (info->IsMobility && !IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - RADEONSetDynamicClock(pScrn, 1); - } else { - RADEONSetDynamicClock(pScrn, 0); + if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Color tiling not supported with virtual x resolutions larger than %d, disabling\n", + info->MaxSurfaceWidth); + info->allowColorTiling = FALSE; } - } else if (IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - atombios_static_pwrmgt_setup(pScrn, 1); - atombios_dyn_clk_setup(pScrn, 1); + if (info->allowColorTiling) { + info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; } + } - - if (IS_R300_VARIANT || IS_RV100_VARIANT) - RADEONForceSomeClocks(pScrn); - - if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Color tiling not supported with virtual x resolutions larger than %d, disabling\n", - info->MaxSurfaceWidth); - info->allowColorTiling = FALSE; - } - if (info->allowColorTiling) { - info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; - } - /* Visual setup */ miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, @@ -3284,19 +3400,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, hasDRI = info->directRenderingEnabled; #endif /* XF86DRI */ - /* Initialize the memory map, this basically calculates the values - * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION - */ - RADEONInitMemoryMap(pScrn); + if (!info->drm_mode_setting) { + /* Initialize the memory map, this basically calculates the values + * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION + */ + RADEONInitMemoryMap(pScrn); - /* empty the surfaces */ - { - unsigned char *RADEONMMIO = info->MMIO; - unsigned int j; - for (j = 0; j < 8; j++) { - OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0); - OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0); - OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0); + /* empty the surfaces */ + { + unsigned char *RADEONMMIO = info->MMIO; + unsigned int j; + for (j = 0; j < 8; j++) { + OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0); + } } } @@ -3341,6 +3459,9 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, from = X_CONFIG; } + if (info->drm_mm) + info->accelDFS = FALSE; + /* Reserve approx. half of offscreen memory for local textures by * default, can be overridden with Option "FBTexPercent". * Round down to a whole number of texture regions. @@ -3369,7 +3490,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif #if defined(XF86DRI) && defined(USE_XAA) - if (!info->useEXA && hasDRI) { + if (!info->useEXA && hasDRI && !info->drm_mm) { info->textureSize = -1; if (xf86GetOptValInteger(info->Options, OPTION_FBTEX_PERCENT, &(info->textureSize))) { @@ -3387,7 +3508,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif #ifdef USE_XAA - if (!info->useEXA && !hasDRI && !RADEONSetupMemXAA(scrnIndex, pScreen)) + if (!info->useEXA && !hasDRI && !info->drm_mm && !RADEONSetupMemXAA(scrnIndex, pScreen)) return FALSE; #endif @@ -3407,7 +3528,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->CurrentLayout.pixel_bytes); int maxy = info->FbMapSize / width_bytes; - if (maxy <= pScrn->virtualY * 3) { + if (maxy <= pScrn->virtualY * 3 && !info->drm_mm) { xf86DrvMsg(scrnIndex, X_ERROR, "Static buffer allocation failed. Disabling DRI.\n"); xf86DrvMsg(scrnIndex, X_ERROR, @@ -3421,15 +3542,39 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } - /* Tell DRI about new memory map */ - if (info->directRenderingEnabled && info->newMemoryMap) { - if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { + front_ptr = info->FB; + if (info->drm_mm) { + if (info->directRenderingEnabled && info->newMemoryMap) { + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "[drm] failed to enable new memory map\n"); RADEONDRICloseScreen(pScreen); info->directRenderingEnabled = FALSE; + } + } + info->bufmgr = radeon_bufmgr_gem_init(info->drmFD); + drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr); + //radeon_bufmgr_gem_enable_reuse(info->bufmgr); + radeon_setup_kernel_mem(pScreen); + front_ptr = info->mm.front_buffer->map; + pScrn->fbOffset = info->mm.front_buffer->offset; + info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) + << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10)); + } else { + + /* Tell DRI about new memory map */ + if (info->directRenderingEnabled && info->newMemoryMap) { + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[drm] failed to enable new memory map\n"); + RADEONDRICloseScreen(pScreen); + info->directRenderingEnabled = FALSE; + } } } + + RADEONDRIDoMappings(pScreen); + #endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Initializing fb layer\n"); @@ -3453,7 +3598,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, if (info->r600_shadow_fb == FALSE) { /* Init fb layer */ - if (!fbScreenInit(pScreen, info->FB, + if (!fbScreenInit(pScreen, front_ptr, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) @@ -3508,7 +3653,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* DRI finalisation */ #ifdef XF86DRI - if (info->directRenderingEnabled && info->cardType==CARD_PCIE && + if (!info->drm_mm && info->directRenderingEnabled && info->cardType==CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19) { if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_PCIGART_LOCATION, info->pciGartOffset) < 0) @@ -3527,15 +3672,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); } if (info->directRenderingEnabled) { + + if (info->drm_mm) + radeon_update_dri_buffers(pScrn); + /* DRI final init might have changed the memory map, we need to adjust * our local image to make sure we restore them properly on mode * changes or VT switches */ - RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); + if (!info->drm_mode_setting) { + RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); - if ((info->DispPriority == 1) && (info->cardType==CARD_AGP)) { - /* we need to re-calculate bandwidth because of AGPMode difference. */ - RADEONInitDispBandwidth(pScrn); + if ((info->DispPriority == 1) && (info->cardType==CARD_AGP)) { + /* we need to re-calculate bandwidth because of AGPMode difference. */ + RADEONInitDispBandwidth(pScrn); + } } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); @@ -5355,6 +5506,11 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) xf86OutputPtr output = config->output[config->compat_output]; xf86CrtcPtr crtc = output->crtc; + if (info->drm_mode_setting) { + drmmode_adjust_frame(pScrn, &info->drmmode, x, y, flags); + return; + } + #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); #endif @@ -5390,67 +5546,80 @@ Bool RADEONEnterVT(int scrnIndex, int flags) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONEnterVT\n"); - if (!radeon_card_posted(pScrn)) { /* Softboot V_BIOS */ - if (info->IsAtomBios) { - rhdAtomASICInit(info->atomBIOS); - } else { - xf86Int10InfoPtr pInt; + if (!info->drm_mode_setting) { + if (!radeon_card_posted(pScrn)) { /* Softboot V_BIOS */ + if (info->IsAtomBios) { + rhdAtomASICInit(info->atomBIOS); + } else { + xf86Int10InfoPtr pInt; + + pInt = xf86InitInt10 (info->pEnt->index); + if (pInt) { + pInt->num = 0xe6; + xf86ExecX86int10 (pInt); + xf86FreeInt10 (pInt); + } else { + RADEONGetBIOSInitTableOffsets(pScrn); + RADEONPostCardFromBIOSTables(pScrn); + } + } + } + /* Makes sure the engine is idle before doing anything */ + RADEONWaitForIdleMMIO(pScrn); - pInt = xf86InitInt10 (info->pEnt->index); - if (pInt) { - pInt->num = 0xe6; - xf86ExecX86int10 (pInt); - xf86FreeInt10 (pInt); + if (info->IsMobility && !IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + RADEONSetDynamicClock(pScrn, 1); } else { - RADEONGetBIOSInitTableOffsets(pScrn); - RADEONPostCardFromBIOSTables(pScrn); + RADEONSetDynamicClock(pScrn, 0); + } + } else if (IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + atombios_static_pwrmgt_setup(pScrn, 1); + atombios_dyn_clk_setup(pScrn, 1); } } - } - - /* Makes sure the engine is idle before doing anything */ - RADEONWaitForIdleMMIO(pScrn); + + if (IS_R300_VARIANT || IS_RV100_VARIANT) + RADEONForceSomeClocks(pScrn); - if (info->IsMobility && !IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - RADEONSetDynamicClock(pScrn, 1); - } else { - RADEONSetDynamicClock(pScrn, 0); - } - } else if (IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - atombios_static_pwrmgt_setup(pScrn, 1); - atombios_dyn_clk_setup(pScrn, 1); - } } - if (IS_R300_VARIANT || IS_RV100_VARIANT) - RADEONForceSomeClocks(pScrn); + if (info->drm_mm) { + radeon_bind_all_memory(pScrn); + info->XInited3D = FALSE; + info->engineMode = EXA_ENGINEMODE_UNKNOWN; + } - for (i = 0; i < config->num_crtc; i++) - radeon_crtc_modeset_ioctl(config->crtc[i], TRUE); + radeon_update_dri_buffers(pScrn); pScrn->vtSema = TRUE; + if (!info->drm_mode_setting) + for (i = 0; i < config->num_crtc; i++) + radeon_crtc_modeset_ioctl(config->crtc[i], TRUE); + if (!xf86SetDesiredModes(pScrn)) return FALSE; - if (info->ChipFamily < CHIP_FAMILY_R600) - RADEONRestoreSurfaces(pScrn, info->ModeReg); + if (!info->drm_mode_setting) { + if (info->ChipFamily < CHIP_FAMILY_R600) + RADEONRestoreSurfaces(pScrn, info->ModeReg); #ifdef XF86DRI - if (info->directRenderingEnabled) { - if (info->cardType == CARD_PCIE && - info->pKernelDRMVersion->version_minor >= 19 && - info->FbSecureSize) { - /* we need to backup the PCIE GART TABLE from fb memory */ - memcpy(info->FB + info->pciGartOffset, info->pciGartBackup, info->pciGartSize); - } - - /* get the DRI back into shape after resume */ - RADEONDRISetVBlankInterrupt (pScrn, TRUE); - RADEONDRIResume(pScrn->pScreen); - RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); - + if (info->directRenderingEnabled) { + if (info->cardType == CARD_PCIE && + info->pKernelDRMVersion->version_minor >= 19 && + info->FbSecureSize) { + /* we need to backup the PCIE GART TABLE from fb memory */ + memcpy(info->FB + info->pciGartOffset, info->pciGartBackup, info->pciGartSize); + } + + /* get the DRI back into shape after resume */ + RADEONDRISetVBlankInterrupt (pScrn, TRUE); + RADEONDRIResume(pScrn->pScreen); + RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); + + } } #endif /* this will get XVideo going again, but only if XVideo was initialised @@ -5462,7 +5631,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) RADEONEngineRestore(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled && !info->drm_mode_setting) { RADEONCP_START(pScrn, info); DRIUnlock(pScrn->pScreen); } @@ -5485,24 +5654,26 @@ void RADEONLeaveVT(int scrnIndex, int flags) "RADEONLeaveVT\n"); #ifdef XF86DRI if (RADEONPTR(pScrn)->directRenderingInited) { - - RADEONDRISetVBlankInterrupt (pScrn, FALSE); - DRILock(pScrn->pScreen, 0); - RADEONCP_STOP(pScrn, info); - - if (info->cardType == CARD_PCIE && - info->pKernelDRMVersion->version_minor >= 19 && - info->FbSecureSize) { - /* we need to backup the PCIE GART TABLE from fb memory */ - memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize); - } + + if (!info->drm_mode_setting) { + RADEONDRISetVBlankInterrupt (pScrn, FALSE); + DRILock(pScrn->pScreen, 0); + RADEONCP_STOP(pScrn, info); + + if (info->cardType == CARD_PCIE && + info->pKernelDRMVersion->version_minor >= 19 && + info->FbSecureSize) { + /* we need to backup the PCIE GART TABLE from fb memory */ + memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize); + } + } /* Make sure 3D clients will re-upload textures to video RAM */ if (info->textureSize) { RADEONSAREAPrivPtr pSAREAPriv = (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen); - drmTextureRegionPtr list = pSAREAPriv->texList[0]; - int age = ++pSAREAPriv->texAge[0]; + drmTextureRegionPtr list = pSAREAPriv->tex_list[0]; + int age = ++pSAREAPriv->tex_age[0]; i = 0; @@ -5531,10 +5702,15 @@ void RADEONLeaveVT(int scrnIndex, int flags) xf86_hide_cursors (pScrn); - RADEONRestore(pScrn); + if (info->drm_mm) + radeon_unbind_all_memory(pScrn); - for (i = 0; i < config->num_crtc; i++) - radeon_crtc_modeset_ioctl(config->crtc[i], FALSE); + if (!info->drm_mode_setting) { + RADEONRestore(pScrn); + + for (i = 0; i < config->num_crtc; i++) + radeon_crtc_modeset_ioctl(config->crtc[i], FALSE); + } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Ok, leaving now...\n"); @@ -5579,7 +5755,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) #endif /* USE_XAA */ if (pScrn->vtSema) { - RADEONRestore(pScrn); + if (!info->drm_mode_setting) + RADEONRestore(pScrn); } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, @@ -5614,6 +5791,12 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) info->DGAModes = NULL; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Unmapping memory\n"); + + if (info->drm_mm) { + radeon_unbind_all_memory(pScrn); + radeon_free_all_memory(pScrn); + } + RADEONUnmapMem(pScrn); pScrn->vtSema = FALSE; diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 02fd4fc..7a8569e 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -46,7 +46,11 @@ #endif #include "xf86.h" +#include "radeon_bufmgr_gem.h" +#define RADEON_PIXMAP_IS_FRONTBUFFER 1 + +/* quick hacks lolz */ /***********************************************************************/ #define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86Screens[pScr->myNum]; \ @@ -184,14 +188,26 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) RINFO_FROM_SCREEN(pPix->drawable.pScreen); uint32_t pitch, offset; int bpp; + struct radeon_exa_pixmap_priv *driver_priv; bpp = pPix->drawable.bitsPerPixel; if (bpp == 24) bpp = 8; - offset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset; + driver_priv = exaGetPixmapDriverPrivate(pPix); + + /* validate the pixmap somewhere */ + if (info->new_cs) + offset = 0; + else { + if (driver_priv) + offset = driver_priv->bo->offset; + else + offset = exaGetPixmapOffset(pPix); + + offset += info->fbLocation + pScrn->fbOffset; + } pitch = exaGetPixmapPitch(pPix); - return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); } @@ -199,6 +215,8 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) static unsigned long swapper_surfaces[3]; +#endif + static Bool RADEONPrepareAccess(PixmapPtr pPix, int index) { RINFO_FROM_SCREEN(pPix->drawable.pScreen); @@ -206,7 +224,31 @@ static Bool RADEONPrepareAccess(PixmapPtr pPix, int index) uint32_t offset = exaGetPixmapOffset(pPix); int bpp, soff; uint32_t size, flags; + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (driver_priv) { + + if (driver_priv->bo) { + int ret; + + if (radeon_bufmgr_gem_in_vram (driver_priv->bo)) + RADEONCPFlushIndirect(pScrn, 0); + + //radeon_bufmgr_gem_wait_rendering(driver_priv->bo); + + /* flush IB */ + ret = dri_bo_map(driver_priv->bo, 1); + if (ret) { + FatalError("failed to map pixmap %d\n", ret); + return FALSE; + } + + pPix->devPrivate.ptr = driver_priv->bo->virtual; + } + } +#if X_BYTE_ORDER == X_BIG_ENDIAN /* Front buffer is always set with proper swappers */ if (offset == 0) return TRUE; @@ -262,6 +304,7 @@ static Bool RADEONPrepareAccess(PixmapPtr pPix, int index) OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); swapper_surfaces[index] = offset; +#endif return TRUE; } @@ -271,7 +314,16 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index) unsigned char *RADEONMMIO = info->MMIO; uint32_t offset = exaGetPixmapOffset(pPix); int soff; + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + + if (driver_priv) { + dri_bo_unmap(driver_priv->bo); + } + pPix->devPrivate.ptr = NULL; +#if X_BYTE_ORDER == X_BIG_ENDIAN /* Front buffer is always set with proper swappers */ if (offset == 0) return; @@ -294,13 +346,100 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index) OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); swapper_surfaces[index] = 0; +#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ } -#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ +void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_exa_pixmap_priv *new_priv; + + new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv)); + if (!new_priv) + return NULL; + + if (size == 0) + return new_priv; + + new_priv->bo = dri_bo_alloc(info->bufmgr, "exa pixmap", size, + align, 0); + if (!new_priv->bo) { + xfree(new_priv); + ErrorF("Failed to alloc memory\n"); + return NULL; + } + + return new_priv; + +} + +static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_exa_pixmap_priv *driver_priv = driverPriv; + int ret; + + dri_bo_unreference(driver_priv->bo); + xfree(driverPriv); +} + +static Bool RADEONEXAModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, + int depth, int bitsPerPixel, int devKind, + pointer pPixData) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPixmap); + if (!driver_priv) + return FALSE; + + + if (info->drm_mode_setting && drmmode_is_rotate_pixmap(pScrn, pPixData, &driver_priv->bo)){ + dri_bo_unmap(driver_priv->bo); + dri_bo_reference(driver_priv->bo); + miModifyPixmapHeader(pPixmap, width, height, depth, + bitsPerPixel, devKind, NULL); + + return TRUE; + } + + if (pPixData == info->mm.front_buffer->map) { + driver_priv->flags |= RADEON_PIXMAP_IS_FRONTBUFFER; + + if (info->new_cs) + driver_priv->bo = radeon_bo_gem_create_from_name(info->bufmgr, "front", + radeon_name_buffer(pScrn, info->mm.front_buffer)); + else + driver_priv->bo = radeon_bufmgr_exa_create_bo(info->bufmgr, info->mm.front_buffer); + + miModifyPixmapHeader(pPixmap, width, height, depth, + bitsPerPixel, devKind, NULL); + return TRUE; + } + return FALSE; +} + +static Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) +{ + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + + if (!driver_priv) + return FALSE; + if (driver_priv->bo) + return TRUE; + return FALSE; +} #define RADEON_SWITCH_TO_2D() \ do { \ - uint32_t wait_until = 0; \ + uint32_t wait_until = 0; \ BEGIN_ACCEL(1); \ switch (info->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ @@ -317,7 +456,7 @@ do { \ #define RADEON_SWITCH_TO_3D() \ do { \ - uint32_t wait_until = 0; \ + uint32_t wait_until = 0; \ BEGIN_ACCEL(1); \ switch (info->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ @@ -341,6 +480,7 @@ do { \ #define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) #define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) #define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) +#define OUT_RELOC(x, read, write) do {} while(0) #define FINISH_ACCEL() #ifdef RENDER @@ -353,6 +493,7 @@ do { \ #undef BEGIN_ACCEL #undef OUT_ACCEL_REG #undef FINISH_ACCEL +#undef OUT_RELOC #ifdef XF86DRI @@ -363,6 +504,7 @@ do { \ #define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) #define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) #define FINISH_ACCEL() ADVANCE_RING() +#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) #define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) @@ -373,6 +515,8 @@ do { \ #endif /* XF86DRI */ + + /* * Once screen->off_screen_base is set, this function * allocates the remaining memory appropriately @@ -394,125 +538,124 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen) if (info->exa == NULL) return FALSE; - /* Need to adjust screen size for 16 line tiles, and then make it align to. - * the buffer alignment requirement. - */ - if (info->allowColorTiling) - screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; - else - screen_size = pScrn->virtualY * byteStride; - - info->exa->memoryBase = info->FB; - info->exa->memorySize = info->FbMapSize - info->FbSecureSize; - info->exa->offScreenBase = screen_size; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", - info->exa->memorySize / 1024); - - - /* Reserve static area for hardware cursor */ - if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { - int cursor_size = 64 * 4 * 64; - int align = IS_AVIVO_VARIANT ? 4096 : 256; - int c; - - for (c = 0; c < xf86_config->num_crtc; c++) { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - - radeon_crtc->cursor_offset = - RADEON_ALIGN(info->exa->offScreenBase, align); - info->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for hardware cursor %d at offset 0x%08x\n", - (cursor_size * xf86_config->num_crtc) / 1024, - c, - (unsigned int)radeon_crtc->cursor_offset); - } - - - } - -#if defined(XF86DRI) - if (info->directRenderingEnabled) { - int depthCpp = (info->depthBits - 8) / 4, l, next, depth_size; - - info->frontOffset = 0; - info->frontPitch = pScrn->displayWidth; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for front buffer at offset 0x%08x\n", - screen_size / 1024, info->frontOffset); - RADEONDRIAllocatePCIGARTTable(pScreen); - - if (info->cardType==CARD_PCIE) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for PCI GART at offset 0x%08x\n", - info->pciGartSize / 1024, - (int)info->pciGartOffset); - - /* Reserve a static area for the back buffer the same size as the - * visible screen. XXX: This would be better initialized in ati_dri.c - * when GLX is set up, but the offscreen memory manager's allocations - * don't last through VT switches, while the kernel's understanding of - * offscreen locations does. - */ - info->backPitch = pScrn->displayWidth; - next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN); - if (!info->noBackBuffer && - next + screen_size <= info->exa->memorySize) - { - info->backOffset = next; - info->exa->offScreenBase = next + screen_size; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for back buffer at offset 0x%08x\n", - screen_size / 1024, info->backOffset); - } - - /* Reserve the static depth buffer, and adjust pitch and height to - * handle tiling. + if (info->drm_mm == FALSE) { + /* Need to adjust screen size for 16 line tiles, and then make it align to. + * the buffer alignment requirement. */ - info->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); - depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * depthCpp; - next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN); - if (next + depth_size <= info->exa->memorySize) - { - info->depthOffset = next; - info->exa->offScreenBase = next + depth_size; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for depth buffer at offset 0x%08x\n", - depth_size / 1024, info->depthOffset); + if (info->allowColorTiling) + screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; + else + screen_size = pScrn->virtualY * byteStride; + + info->exa->memoryBase = info->FB; + info->exa->memorySize = info->FbMapSize - info->FbSecureSize; + info->exa->offScreenBase = screen_size; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", + info->exa->memorySize / 1024); + + + /* Reserve static area for hardware cursor */ + if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { + int cursor_size = 64 * 4 * 64; + int align = IS_AVIVO_VARIANT ? 4096 : 256; + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + radeon_crtc->cursor_offset = + RADEON_ALIGN(info->exa->offScreenBase, align); + info->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for hardware cursor %d at offset 0x%08x\n", + (cursor_size * xf86_config->num_crtc) / 1024, + c, + (unsigned int)radeon_crtc->cursor_offset); + } } - info->textureSize *= (info->exa->memorySize - - info->exa->offScreenBase) / 100; - - l = RADEONLog2(info->textureSize / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) - l = RADEON_LOG_TEX_GRANULARITY; - info->textureSize = (info->textureSize >> l) << l; - if (info->textureSize >= 512 * 1024) { - info->textureOffset = info->exa->offScreenBase; - info->exa->offScreenBase += info->textureSize; +#if defined(XF86DRI) + if (info->directRenderingEnabled) { + int depthCpp = (info->depthBits - 8) / 4, l, next, depth_size; + + info->frontOffset = 0; + info->frontPitch = pScrn->displayWidth; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for textures at offset 0x%08x\n", - info->textureSize / 1024, info->textureOffset); - } else { - /* Minimum texture size is for 2 256x256x32bpp textures */ - info->textureSize = 0; - } - } else + "Will use %d kb for front buffer at offset 0x%08x\n", + screen_size / 1024, info->frontOffset); + RADEONDRIAllocatePCIGARTTable(pScreen); + + if (info->cardType==CARD_PCIE) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for PCI GART at offset 0x%08x\n", + info->pciGartSize / 1024, + (int)info->pciGartOffset); + + /* Reserve a static area for the back buffer the same size as the + * visible screen. XXX: This would be better initialized in ati_dri.c + * when GLX is set up, but the offscreen memory manager's allocations + * don't last through VT switches, while the kernel's understanding of + * offscreen locations does. + */ + info->backPitch = pScrn->displayWidth; + next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN); + if (!info->noBackBuffer && + next + screen_size <= info->exa->memorySize) + { + info->backOffset = next; + info->exa->offScreenBase = next + screen_size; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for back buffer at offset 0x%08x\n", + screen_size / 1024, info->backOffset); + } + + /* Reserve the static depth buffer, and adjust pitch and height to + * handle tiling. + */ + info->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); + depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * depthCpp; + next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN); + if (next + depth_size <= info->exa->memorySize) + { + info->depthOffset = next; + info->exa->offScreenBase = next + depth_size; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for depth buffer at offset 0x%08x\n", + depth_size / 1024, info->depthOffset); + } + + info->textureSize *= (info->exa->memorySize - + info->exa->offScreenBase) / 100; + + l = RADEONLog2(info->textureSize / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) + l = RADEON_LOG_TEX_GRANULARITY; + info->textureSize = (info->textureSize >> l) << l; + if (info->textureSize >= 512 * 1024) { + info->textureOffset = info->exa->offScreenBase; + info->exa->offScreenBase += info->textureSize; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for textures at offset 0x%08x\n", + info->textureSize / 1024, info->textureOffset); + } else { + /* Minimum texture size is for 2 256x256x32bpp textures */ + info->textureSize = 0; + } + } else #endif /* XF86DRI */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Will use %d kb for front buffer at offset 0x%08x\n", screen_size / 1024, 0); - + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", (info->exa->memorySize - info->exa->offScreenBase) / 1024, info->exa->offScreenBase); - + } return TRUE; } @@ -525,10 +668,21 @@ extern void ExaOffscreenMarkUsed(PixmapPtr); unsigned long long RADEONTexOffsetStart(PixmapPtr pPix) { + struct radeon_exa_pixmap_priv *driver_priv; + uint32_t offset; + driver_priv = exaGetPixmapDriverPrivate(pPix); + + if (driver_priv) { + offset = driver_priv->bo->offset; + + } else { + offset = exaGetPixmapOffset(pPix); + offset += RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation; + } exaMoveInPixmap(pPix); ExaOffscreenMarkUsed(pPix); + - return RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation + - exaGetPixmapOffset(pPix); + return offset; } #endif diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index 56de23e..dfa74a1 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -74,21 +74,78 @@ FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); + if (info->new_cs) + return; + TRACE; if (info->exaMarkerSynced != marker) { - FUNC_NAME(RADEONWaitForIdle)(pScrn); + FUNC_NAME(RADEONWaitForIdle)(pScrn); info->exaMarkerSynced = marker; } RADEONPTR(pScrn)->engineMode = EXA_ENGINEMODE_UNKNOWN; } +static void FUNC_NAME(Emit2DState)(ScrnInfoPtr pScrn, int op) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + uint32_t qwords; + int has_src; + ACCEL_PREAMBLE(); + + /* don't emit if no operation in progress */ + if (info->state_2d.op == 0 && op == 0) + return; + + has_src = info->state_2d.src_pitch_offset || (info->new_cs && info->state_2d.src_bo); + + qwords = info->new_cs ? 11 : 9; + qwords += (has_src ? (info->new_cs ? 3 : 1) : 0); + qwords += (info->ChipFamily <= CHIP_FAMILY_RV280 ? 3 : 2); + + BEGIN_ACCEL(qwords); + if (info->ChipFamily <= CHIP_FAMILY_RV280) { + OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); + OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, 0x7ff07ff); + OUT_ACCEL_REG(RADEON_AUX_SC_CNTL, 0); + } else { + OUT_ACCEL_REG(R300_SC_SCISSOR0, 0); + OUT_ACCEL_REG(R300_SC_SCISSOR1, 0x7ff07ff); + } + OUT_ACCEL_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right); + OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl); + OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr); + OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr); + OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr); + OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr); + OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, info->state_2d.dp_write_mask); + OUT_ACCEL_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl); + + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); + if (info->new_cs) + OUT_RELOC(info->state_2d.dst_bo, 0, RADEON_GEM_DOMAIN_VRAM); + + if (has_src) { + OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset); + if (info->new_cs) + OUT_RELOC(info->state_2d.src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); + + } + FINISH_ACCEL(); + + if (op) + info->state_2d.op = op; + if (info->new_cs) + info->reemit_current2d = FUNC_NAME(Emit2DState); +} + static Bool FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) { RINFO_FROM_SCREEN(pPix->drawable.pScreen); uint32_t datatype, dst_pitch_offset; + struct radeon_exa_pixmap_priv *driver_priv; ACCEL_PREAMBLE(); TRACE; @@ -97,25 +154,35 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) RADEON_FALLBACK(("24bpp unsupported\n")); if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype)) RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); + if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset)) - RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n")); + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n")); RADEON_SWITCH_TO_2D(); - BEGIN_ACCEL(5); - OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_SOLID_COLOR | - (datatype << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP[alu].pattern | - RADEON_GMC_CLR_CMP_CNTL_DIS); - OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); - OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, pm); - OUT_ACCEL_REG(RADEON_DP_CNTL, - (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM)); - OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); - FINISH_ACCEL(); + info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX | + RADEON_DEFAULT_SC_BOTTOM_MAX); + info->state_2d.dp_brush_bkgd_clr = 0x00000000; + info->state_2d.dp_src_frgd_clr = 0xffffffff; + info->state_2d.dp_src_bkgd_clr = 0x00000000; + info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_SOLID_COLOR | + (datatype << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP[alu].pattern | + RADEON_GMC_CLR_CMP_CNTL_DIS); + info->state_2d.dp_brush_frgd_clr = fg; + info->state_2d.dp_cntl = (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM); + info->state_2d.dp_write_mask = pm; + info->state_2d.dst_pitch_offset = dst_pitch_offset; + info->state_2d.src_pitch_offset = 0; + info->state_2d.src_bo = NULL; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (driver_priv) + info->state_2d.dst_bo = driver_priv->bo; + + FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID); return TRUE; } @@ -148,8 +215,10 @@ FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPix) OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); FINISH_ACCEL(); + info->state_2d.op = 0; } + void FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, uint32_t dst_pitch_offset, uint32_t datatype, int rop, @@ -160,23 +229,28 @@ FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, RADEON_SWITCH_TO_2D(); - BEGIN_ACCEL(5); - OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_SRC_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (datatype << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP[rop].rop | - RADEON_DP_SRC_SOURCE_MEMORY | - RADEON_GMC_CLR_CMP_CNTL_DIS); - OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); - OUT_ACCEL_REG(RADEON_DP_CNTL, - ((info->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | - (info->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0))); - OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); - OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); - FINISH_ACCEL(); + /* setup 2D state */ + info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (datatype << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP[rop].rop | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS); + info->state_2d.dp_cntl = ((info->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | + (info->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)); + info->state_2d.dp_brush_frgd_clr = 0xffffffff; + info->state_2d.dp_brush_bkgd_clr = 0x00000000; + info->state_2d.dp_src_frgd_clr = 0xffffffff; + info->state_2d.dp_src_bkgd_clr = 0x00000000; + info->state_2d.dp_write_mask = planemask; + info->state_2d.dst_pitch_offset = dst_pitch_offset; + info->state_2d.src_pitch_offset = src_pitch_offset; + info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX + | RADEON_DEFAULT_SC_BOTTOM_MAX); + + FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY); } static Bool @@ -187,7 +261,7 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, { RINFO_FROM_SCREEN(pDst->drawable.pScreen); uint32_t datatype, src_pitch_offset, dst_pitch_offset; - + struct radeon_exa_pixmap_priv *driver_priv; TRACE; info->xdir = xdir; @@ -197,10 +271,19 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, RADEON_FALLBACK(("24bpp unsupported")); if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype)) RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); + if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset)) - RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) - RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); + + driver_priv = exaGetPixmapDriverPrivate(pSrc); + if (driver_priv) + info->state_2d.src_bo = driver_priv->bo; + + driver_priv = exaGetPixmapDriverPrivate(pDst); + if (driver_priv) + info->state_2d.dst_bo = driver_priv->bo; FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset, datatype, rop, planemask); @@ -250,6 +333,8 @@ FUNC_NAME(RADEONDoneCopy)(PixmapPtr pDst) OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); FINISH_ACCEL(); + + info->state_2d.op = 0; } static Bool @@ -260,6 +345,8 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, uint8_t *dst = info->FB + exaGetPixmapOffset(pDst); unsigned int dst_pitch = exaGetPixmapPitch(pDst); unsigned int bpp = pDst->drawable.bitsPerPixel; + int ret; + struct radeon_exa_pixmap_priv *driver_priv; #ifdef ACCEL_CP unsigned int hpass; uint32_t buf_pitch, dst_pitch_off; @@ -276,10 +363,45 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, if (bpp < 8) return FALSE; + if (info->new_cs) + dst = info->mm.front_buffer->map + exaGetPixmapOffset(pDst); + #ifdef ACCEL_CP - if (info->directRenderingEnabled && - RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) { - uint8_t *buf; + + if (info->new_cs){ + + if (info->drm_mm) { + uint32_t offset, bo_width, bo_height = h; + + driver_priv = exaGetPixmapDriverPrivate(pDst); + if (!driver_priv) + return FALSE; + + + /* use pwrites - maybe require some sort of fallback */ + bo_width = w * (bpp / 8); + offset = (x * bpp / 8) + (y * dst_pitch); + + while (bo_height--) { + dri_bo_subdata(driver_priv->bo, offset, bo_width, + src); + + src += src_pitch; + offset += dst_pitch; + } + + return TRUE; + } + } + if (!info->directRenderingEnabled && !info->drm_mode_setting) + goto fallback; + + if (RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) + goto fallback; + + if (!info->new_cs) + { + uint8_t *buf; int cpp = bpp / 8; ACCEL_PREAMBLE(); @@ -294,9 +416,10 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, exaMarkSync(pDst->drawable.pScreen); return TRUE; - } -#endif + } + fallback: +#endif /* Do we need that sync here ? probably not .... */ exaWaitSync(pDst->drawable.pScreen); @@ -388,13 +511,17 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, TRACE; + if (info->drm_mode_setting) + src = info->mm.front_buffer->map + exaGetPixmapOffset(pSrc); + #ifdef ACCEL_CP /* * Try to accelerate download. Use an indirect buffer as scratch space, * blitting the bits to one half while copying them out of the other one and * then swapping the halves. */ - if (info->accelDFS && bpp != 24 && RADEONGetDatatypeBpp(bpp, &datatype) && + if (!info->drm_mm && info->accelDFS && bpp != 24 && + RADEONGetDatatypeBpp(bpp, &datatype) && RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) && (scratch = RADEONCPGetBuffer(pScrn))) { @@ -540,17 +667,23 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) info->exa->MarkSync = FUNC_NAME(RADEONMarkSync); info->exa->WaitMarker = FUNC_NAME(RADEONSync); + info->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen); - info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); + if (!info->drm_mm) { + info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); + } -#if X_BYTE_ORDER == X_BIG_ENDIAN info->exa->PrepareAccess = RADEONPrepareAccess; info->exa->FinishAccess = RADEONFinishAccess; -#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ info->exa->flags = EXA_OFFSCREEN_PIXMAPS; - info->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1; info->exa->pixmapPitchAlign = 64; + info->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1; + + if (info->drm_mm) { + info->exa->flags |= EXA_HANDLES_PIXMAPS; + } else { + } #ifdef RENDER if (info->RenderAccel) { @@ -560,7 +693,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) else if (IS_R300_3D || IS_R500_3D) { if ((info->ChipFamily < CHIP_FAMILY_RS400) #ifdef XF86DRI - || (info->directRenderingEnabled) + || (info->directRenderingEnabled || info->drm_mode_setting) #endif ) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " @@ -595,6 +728,16 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) } #endif +#if EXA_VERSION_MINOR >= 4 + if (info->drm_mm) { + info->exa->CreatePixmap = RADEONEXACreatePixmap; + info->exa->DestroyPixmap = RADEONEXADestroyPixmap; + info->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; + info->exa->ModifyPixmapHeader = RADEONEXAModifyPixmapHeader; + } +#endif + + #if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n"); diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c index 043b0d4..8f98e92 100644 --- a/src/radeon_exa_render.c +++ b/src/radeon_exa_render.c @@ -410,19 +410,22 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix, if (unit == 0) { OUT_ACCEL_REG(RADEON_PP_TXFILTER_0, txfilter); OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat); - OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset); OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_0, (pPix->drawable.width - 1) | ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_0, txpitch - 32); + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset); + /* emit a texture relocation */ } else { OUT_ACCEL_REG(RADEON_PP_TXFILTER_1, txfilter); OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat); - OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset); + OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_1, (pPix->drawable.width - 1) | ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_1, txpitch - 32); + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset); + /* emit a texture relocation */ } FINISH_ACCEL(); @@ -730,6 +733,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix, ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(R200_PP_TXPITCH_0, txpitch - 32); OUT_ACCEL_REG(R200_PP_TXOFFSET_0, txoffset); + /* emit a texture relocation */ } else { OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter); OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat); @@ -738,6 +742,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix, ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch - 32); OUT_ACCEL_REG(R200_PP_TXOFFSET_1, txoffset); + /* emit a texture relocation */ } FINISH_ACCEL(); @@ -1002,15 +1007,19 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix, int w = pPict->pDrawable->width; int h = pPict->pDrawable->height; int i, pixel_shift; + struct radeon_exa_pixmap_priv *driver_priv; + int qwords; ACCEL_PREAMBLE(); TRACE; txpitch = exaGetPixmapPitch(pPix); - txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset; + txoffset = exaGetPixmapOffset(pPix); - if ((txoffset & 0x1f) != 0) - RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + if (!info->new_cs) { + if ((txoffset & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + } if ((txpitch & 0x1f) != 0) RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch)); @@ -1071,13 +1080,25 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix, RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter)); } - BEGIN_ACCEL(pPict->repeat ? 6 : 7); + qwords = pPict->repeat ? 6 : 7; + qwords += info->new_cs ? 2 : 0; + + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(R300_TX_FILTER0_0 + (unit * 4), txfilter); OUT_ACCEL_REG(R300_TX_FILTER1_0 + (unit * 4), 0); OUT_ACCEL_REG(R300_TX_FORMAT0_0 + (unit * 4), txformat0); OUT_ACCEL_REG(R300_TX_FORMAT1_0 + (unit * 4), txformat1); OUT_ACCEL_REG(R300_TX_FORMAT2_0 + (unit * 4), txpitch); - OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset); + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (info->new_cs) { + uint32_t handle = 0; + OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), driver_priv ? 0 : txoffset); + OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset); + } if (!pPict->repeat) OUT_ACCEL_REG(R300_TX_BORDER_COLOR_0 + (unit * 4), 0); FINISH_ACCEL(); @@ -1187,6 +1208,8 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, uint32_t txenable, colorpitch; uint32_t blendcntl; int pixel_shift; + int qwords; + struct radeon_exa_pixmap_priv *driver_priv; ACCEL_PREAMBLE(); TRACE; @@ -1204,7 +1227,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, pixel_shift = pDst->drawable.bitsPerPixel >> 4; - dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset; + dst_offset = exaGetPixmapOffset(pDst); dst_pitch = exaGetPixmapPitch(pDst); colorpitch = dst_pitch >> pixel_shift; @@ -1213,7 +1236,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, colorpitch |= dst_format; - if ((dst_offset & 0x0f) != 0) + if (!info->new_cs && ((dst_offset & 0x0f) != 0)) RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset)); if (((dst_pitch >> pixel_shift) & 0x7) != 0) RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch)); @@ -1832,9 +1855,18 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, FINISH_ACCEL(); } - BEGIN_ACCEL(3); + qwords = info->new_cs ? 5 : 3; + BEGIN_ACCEL(qwords); + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pDst); + assert(driver_priv); - OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, 0); + OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + } else { + dst_offset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); + } OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch); blendcntl = RADEONGetBlendCntl(op, pMaskPicture, pDstPicture->format); diff --git a/src/radeon_memory.c b/src/radeon_memory.c new file mode 100644 index 0000000..6c01dd9 --- /dev/null +++ b/src/radeon_memory.c @@ -0,0 +1,428 @@ + +#include +#include +#include +#include "radeon.h" +#include "radeon_drm.h" + +Bool +radeon_bind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (mem == NULL || mem->bound) + return TRUE; + + if (!info->drm_mm) + return FALSE; + + if (mem->kernel_bo_handle) { + struct drm_radeon_gem_pin pin; + + int ret; + + if (mem->pool == RADEON_POOL_VRAM) + pin.pin_domain = RADEON_GEM_DOMAIN_VRAM; + else + pin.pin_domain = RADEON_GEM_DOMAIN_GTT; + pin.handle = mem->kernel_bo_handle; + pin.alignment = mem->alignment; + + ret = ioctl(info->drmFD, DRM_IOCTL_RADEON_GEM_PIN, &pin); + if (ret != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to pin %s: %s\n", mem->name, strerror(errno)); + return FALSE; + } + + mem->bound = TRUE; + mem->offset = pin.offset; + // ErrorF("pin returned 0x%llx\n", pin.offset); + mem->end = mem->offset + mem->size; + return TRUE; + } + return FALSE; +} + +static Bool +radeon_unbind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int ret; + + if (mem == NULL || !mem->bound) + return TRUE; + + if (!info->drm_mm) + return FALSE; + + + if (mem->kernel_bo_handle) { + struct drm_radeon_gem_unpin unpin; + + unpin.handle = mem->kernel_bo_handle; + ret = ioctl(info->drmFD, DRM_IOCTL_RADEON_GEM_UNPIN, &unpin); + + if (ret == 0) { + mem->bound = FALSE; + mem->offset = -1; + mem->end = -1; + return TRUE; + } else { + return FALSE; + } + } + return FALSE; +} + +void radeon_free_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (mem == NULL) + return; + + if (mem->map) + radeon_unmap_memory(pScrn, mem); + + radeon_unbind_memory(pScrn, mem); + + if (mem->kernel_bo_handle) { + struct drm_gem_close close; + + close.handle = mem->kernel_bo_handle; + ioctl(info->drmFD, DRM_IOCTL_GEM_CLOSE, &close); + } + + if (info->mm.bo_list[mem->pool] == mem) { + info->mm.bo_list[mem->pool] = mem->next; + if (mem->next) + mem->next->prev = NULL; + } else { + if (mem->prev) + mem->prev->next = mem->next; + if (mem->next) + mem->next->prev = mem->prev; + } + xfree(mem->name); + xfree(mem); + return; +} + +struct radeon_memory *radeon_allocate_memory(ScrnInfoPtr pScrn, int pool, int size, int alignment, Bool no_backing_store, char *name, + int static_alloc) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_radeon_gem_create args; + struct radeon_memory *mem; + int ret; + + mem = xcalloc(1, sizeof(*mem)); + if (!mem) + return NULL; + + mem->name = xstrdup(name); + if (!mem->name) { + xfree(mem); + return NULL; + } + + mem->size = size; + mem->pool = pool; + mem->next = mem->prev = NULL; + mem->vt_bind = static_alloc; + args.size = size; + args.alignment = alignment; + if (pool == RADEON_POOL_VRAM) + args.initial_domain = RADEON_GEM_DOMAIN_VRAM; + else + args.initial_domain = RADEON_GEM_DOMAIN_GTT; + args.no_backing_store = no_backing_store; + + ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_CREATE, &args, sizeof(args)); + if (ret) { + ErrorF("Failed to allocate %s\n", mem->name); + xfree(mem); + return NULL; + } + + mem->kernel_bo_handle = args.handle; + // xf86DrvMsg(pScrn->scrnIndex, X_INFO, + // "%s allocated %d with handle %x\n", mem->name, mem->size, mem->kernel_bo_handle); + + /* add to VRAM linked list for now */ + + mem->prev = NULL; + mem->next = info->mm.bo_list[pool]; + if (info->mm.bo_list[pool] != NULL) + info->mm.bo_list[pool]->prev = mem; + info->mm.bo_list[pool] = mem; + return mem; +} + +Bool radeon_bind_all_memory(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_memory *mem; + int i; + + for (i = 0; i < 2; i++) { + for (mem = info->mm.bo_list[i]; mem != NULL; + mem = mem->next) { + if (mem->vt_bind) + if (!radeon_bind_memory(pScrn, mem)) { + FatalError("Couldn't bind %s\n", mem->name); + } + } + } + return TRUE; +} + +Bool radeon_unbind_all_memory(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_memory *mem; + int i; + + for (i = 0; i < 2; i++) { + for (mem = info->mm.bo_list[i]; mem != NULL; + mem = mem->next) { + if (mem->vt_bind) + radeon_unbind_memory(pScrn, mem); + } + } + return TRUE; +} + +Bool radeon_free_all_memory(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_memory *mem; + int i; + + for (i = 0; i < 2; i++) { + for (mem = info->mm.bo_list[i]; mem != NULL; + mem = mem->next) { + radeon_free_memory(pScrn, mem); + } + } + return TRUE; +} + +int radeon_map_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + struct drm_radeon_gem_mmap args; + RADEONInfoPtr info = RADEONPTR(pScrn); + int ret; + + assert(!mem->map); + + + args.handle = mem->kernel_bo_handle; + args.size = mem->size; + ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_MMAP, &args, sizeof(args)); + + if (!ret) + mem->map = (void *)(unsigned long)args.addr_ptr; + // ErrorF("Mapped %s size %ld at %x %p\n", mem->name, mem->size, mem->offset, mem->map); + return ret; +} + +void radeon_unmap_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + assert(mem->map); + if (mem->map) { + munmap(mem->map, mem->size); + mem->map = NULL; + } +} + +/* Okay radeon + 2D allocations + - Front buffer + - cursors + - EXA space + + 3D related: + - Backbuffer + - Depth buffer + - textures +*/ + + +Bool radeon_setup_kernel_mem(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + int screen_size; + int stride = pScrn->displayWidth * cpp; + int total_size_bytes = (20*1024*1024)+32*1024, remain_size_bytes; + int fb_size_bytes; + + screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * stride; + + ErrorF("%d x %d x %d = %dK\n", pScrn->displayWidth, pScrn->virtualY, cpp, screen_size / 1024); + + { + int cursor_size = 64 * 4 * 64; + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + /* cursor objects */ + info->mm.cursor[c] = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, cursor_size, 0, 1, "Cursor", 1); + if (!info->mm.cursor[c]) { + return FALSE; + } + + radeon_bind_memory(pScrn, info->mm.cursor[c]); + + if (radeon_map_memory(pScrn, info->mm.cursor[c])) { + ErrorF("Failed to map front buffer memory\n"); + } + + if (!info->drm_mode_setting) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + radeon_crtc->cursor = info->mm.cursor[c]; + } else { + drmmode_set_cursor(pScrn, &info->drmmode, c, (void *)info->mm.cursor[c]->map, info->mm.cursor[c]->kernel_bo_handle); + } + total_size_bytes += cursor_size; + } + } + +#if 0 + info->mm.front_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, screen_size, 0, 1, "Front Buffer"); + if (!info->mm.front_buffer) { + return FALSE; + } + + radeon_bind_memory(pScrn, info->mm.front_buffer); + + if (radeon_map_memory(pScrn, info->mm.front_buffer)) { + ErrorF("Failed to map front buffer memory\n"); + } +#endif + /* keep area front front buffer - but don't allocate it yet */ + total_size_bytes += screen_size; + + if (info->directRenderingEnabled) { + info->backPitch = pScrn->displayWidth; + info->mm.back_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, screen_size, 0, 1, "Back Buffer", 1); + if (!info->mm.back_buffer) { + return FALSE; + } + radeon_bind_memory(pScrn, info->mm.back_buffer); + total_size_bytes += screen_size; + + info->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); + { + int depthCpp = (info->depthBits - 8) / 4; + int depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * depthCpp; + info->mm.depth_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, depth_size, 0, 1, "Depth Buffer", 1); + if (!info->mm.depth_buffer) { + return FALSE; + } + radeon_bind_memory(pScrn, info->mm.depth_buffer); + total_size_bytes += depth_size; + } + } + /* work out from the mm size what the exa / tex sizes need to be */ + remain_size_bytes = info->mm.vram_size - total_size_bytes; + + info->textureSize = remain_size_bytes / 2; + + ErrorF("texture size is %dK, exa is %dK\n", info->textureSize / 1024, (remain_size_bytes - info->textureSize)/1024); + + /* allocate an object for all the EXA bits */ + /* shove EXA + frontbuffer together until we have EXA pixmap hooks */ + fb_size_bytes = screen_size + (remain_size_bytes - info->textureSize); + + if (info->new_cs) + fb_size_bytes = screen_size; + ErrorF("fb size is %dK %dK\n", fb_size_bytes / 1024, total_size_bytes / 1024); + + info->mm.front_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, fb_size_bytes, 0, 1, "Front Buffer + EXA", 1); + if (!info->mm.front_buffer) { + return FALSE; + } + + radeon_bind_memory(pScrn, info->mm.front_buffer); + if (radeon_map_memory(pScrn, info->mm.front_buffer)) { + ErrorF("Failed to map front buffer memory\n"); + } + info->frontPitch = pScrn->displayWidth; +#if 0 + info->mm.exa_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, remain_size_bytes - info->textureSize, 0, 1, "EXA Memory Buffer"); + if (!info->mm.exa_buffer) { + return FALSE; + } + radeon_bind_memory(pScrn, info->mm.exa_buffer); + if (radeon_map_memory(pScrn, info->mm.exa_buffer)) { + ErrorF("Failed to map front buffer memory\n"); + } +#endif + + if (!info->new_cs) { + info->exa->memoryBase = info->mm.front_buffer->map; + info->exa->offScreenBase = screen_size; + info->exa->memorySize = fb_size_bytes; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", + (info->exa->memorySize - info->exa->offScreenBase) / + 1024, info->exa->offScreenBase); + } + + if (info->directRenderingEnabled) { + info->textureSize /= 2; + info->mm.texture_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, info->textureSize, 0, 1, "Texture Buffer", 1); + if (!info->mm.texture_buffer) { + return FALSE; + } + radeon_bind_memory(pScrn, info->mm.texture_buffer); + } + + if (info->drm_mode_setting) { + drmmode_set_fb(pScrn, &info->drmmode, pScrn->virtualX, RADEON_ALIGN(pScrn->virtualY, 16), stride, info->mm.front_buffer->kernel_bo_handle); + } + return TRUE; +} + +Bool radeon_setup_gart_mem(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + + info->mm.gart_texture_buffer = + radeon_allocate_memory(pScrn, RADEON_POOL_GART, + info->gartTexMapSize, + 0, 1, "GART texture buffers", 1); + + if (!info->mm.gart_texture_buffer) { + return FALSE; + } + + radeon_bind_memory(pScrn, info->mm.gart_texture_buffer); + return TRUE; +} + +uint32_t radeon_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch) +{ + return 0; +} + + +dri_bo *radeon_create_rotate_bo(ScrnInfoPtr pScrn, int size) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + dri_bo *bo; + + bo = dri_bo_alloc(info->bufmgr, "rotate", size, 0, 0); + + radeon_bufmgr_pin(bo); + return bo; +} + diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 3770abf..e8505b7 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -182,6 +182,27 @@ typedef struct uint32_t a_data_mask; } RADEONI2CBusRec, *RADEONI2CBusPtr; +struct radeon_memory { + int pool; // memory is VRAM vs GART + unsigned long offset; + unsigned long end; + + unsigned long size; + unsigned long allocated_size; + void *map; + int key; + + Bool bound; + unsigned long agp_offset; + unsigned int pitch; + char *name; + struct radeon_memory *next, *prev; + uint32_t alignment; + uint32_t kernel_bo_handle; + uint32_t kernel_name; + Bool vt_bind; +}; + typedef struct _RADEONCrtcPrivateRec { #ifdef USE_XAA FBLinearPtr rotate_mem_xaa; @@ -198,6 +219,8 @@ typedef struct _RADEONCrtcPrivateRec { uint32_t crtc_offset; int can_tile; Bool enabled; + struct radeon_memory *cursor; + } RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr; typedef struct { diff --git a/src/radeon_sarea.h b/src/radeon_sarea.h index 80333a4..c33632b 100644 --- a/src/radeon_sarea.h +++ b/src/radeon_sarea.h @@ -36,6 +36,7 @@ #ifndef _RADEON_SAREA_H_ #define _RADEON_SAREA_H_ +#if 0 /* WARNING: If you change any of these defines, make sure to change the * defines in the kernel file (radeon_drm.h) */ @@ -229,3 +230,6 @@ typedef struct { } RADEONSAREAPriv, *RADEONSAREAPrivPtr; #endif + +typedef drm_radeon_sarea_t RADEONSAREAPriv, *RADEONSAREAPrivPtr; +#endif diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c index da1d60f..f93cded 100644 --- a/src/radeon_textured_video.c +++ b/src/radeon_textured_video.c @@ -85,6 +85,7 @@ static __inline__ uint32_t F_TO_DW(float val) #define BEGIN_VIDEO(n) RADEONWaitForFifo(pScrn, (n)) #define OUT_VIDEO_REG(reg, val) OUTREG(reg, val) #define OUT_VIDEO_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) +#define OUT_RELOC(x, read, write) do {} while(0) #define FINISH_VIDEO() #include "radeon_textured_videofuncs.c" @@ -94,6 +95,7 @@ static __inline__ uint32_t F_TO_DW(float val) #undef BEGIN_VIDEO #undef OUT_VIDEO_REG #undef OUT_VIDEO_REG_F +#undef OUT_RELOC #undef FINISH_VIDEO #ifdef XF86DRI @@ -107,6 +109,7 @@ static __inline__ uint32_t F_TO_DW(float val) #define OUT_VIDEO_REG_F(reg, val) OUT_VIDEO_REG(reg, F_TO_DW(val)) #define FINISH_VIDEO() ADVANCE_RING() #define OUT_VIDEO_RING_F(x) OUT_RING(F_TO_DW(x)) +#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) #include "radeon_textured_videofuncs.c" @@ -181,7 +184,8 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, } #ifdef XF86DRI - if (info->directRenderingEnabled && info->DMAForXv) + if ((info->directRenderingEnabled || info->drm_mode_setting) + && info->DMAForXv ) /* The upload blit only supports multiples of 64 bytes */ dstPitch = (dstPitch + 63) & ~63; else @@ -195,10 +199,13 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, if (pPriv->video_memory == NULL) { pPriv->video_offset = RADEONAllocateMemory(pScrn, - &pPriv->video_memory, - size * 2); + &pPriv->video_memory, + size * 2); if (pPriv->video_offset == 0) return BadAlloc; + + if (info->new_cs) + pPriv->src_bo = pPriv->video_memory; } /* Bicubic filter loading */ @@ -211,6 +218,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, pPriv->bicubic_src_offset = pPriv->bicubic_offset + info->fbLocation + pScrn->fbOffset; if (pPriv->bicubic_offset == 0) pPriv->bicubic_enabled = FALSE; + + if (info->new_cs) + pPriv->bicubic_bo = pPriv->bicubic_memory; } if (pDraw->type == DRAWABLE_WINDOW) @@ -240,8 +250,19 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, left = (x1 >> 16) & ~1; npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; - pPriv->src_offset = pPriv->video_offset + info->fbLocation + pScrn->fbOffset; - pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch)); + pPriv->src_offset = pPriv->video_offset; + if (info->new_cs) { + int ret; + ret = dri_bo_map(pPriv->src_bo, 1); + if (ret) + return BadAlloc; + + pPriv->src_addr = pPriv->src_bo->virtual; + } else if (info->drm_mm) { + pPriv->src_addr = (uint8_t *)(info->mm.front_buffer->map + pPriv->video_offset + (top * dstPitch)); + } else { + pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch)); + } pPriv->src_pitch = dstPitch; pPriv->size = size; pPriv->pDraw = pDraw; @@ -282,8 +303,24 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, } /* Upload bicubic filter tex */ - if (pPriv->bicubic_enabled) - RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, (uint8_t *)(info->FB + pPriv->bicubic_offset), 1024, 1024, 1, 512, 2); + if (pPriv->bicubic_enabled) { + uint8_t *bicubic_addr; + int ret; + + if (info->new_cs) { + ret = dri_bo_map(pPriv->bicubic_bo, 1); + if (ret) + return BadAlloc; + + bicubic_addr = pPriv->bicubic_bo->virtual; + } else + bicubic_addr = (uint8_t *)(info->FB + pPriv->bicubic_offset); + + RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, bicubic_addr, 1024, 1024, 1, 512, 2); + + if (info->new_cs) + dri_bo_unmap(pPriv->bicubic_bo); + } /* update cliplist */ if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { @@ -300,8 +337,10 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, pPriv->w = width; pPriv->h = height; + if (info->new_cs) + dri_bo_unmap(pPriv->src_bo); #ifdef XF86DRI - if (info->directRenderingEnabled) + if (info->directRenderingEnabled || info->drm_mode_setting) RADEONDisplayTexturedVideoCP(pScrn, pPriv); else #endif diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c index b53e114..d3574f4 100644 --- a/src/radeon_textured_videofuncs.c +++ b/src/radeon_textured_videofuncs.c @@ -95,6 +95,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv { RADEONInfoPtr info = RADEONPTR(pScrn); PixmapPtr pPixmap = pPriv->pPixmap; + struct radeon_exa_pixmap_priv *driver_priv; + dri_bo *dst_bo; uint32_t txformat; uint32_t txfilter, txformat0, txformat1, txoffset, txpitch; uint32_t dst_offset, dst_pitch, dst_format; @@ -103,19 +105,25 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv int dstxoff, dstyoff, pixel_shift, vtx_count; BoxPtr pBox = REGION_RECTS(&pPriv->clip); int nBox = REGION_NUM_RECTS(&pPriv->clip); + int qwords; VIDEO_PREAMBLE(); pixel_shift = pPixmap->drawable.bitsPerPixel >> 4; #ifdef USE_EXA if (info->useEXA) { - dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset; + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pPixmap); + if (driver_priv) + dst_bo = driver_priv->bo; + } else { + dst_offset = exaGetPixmapOffset(pPixmap); + } dst_pitch = exaGetPixmapPitch(pPixmap); } else #endif { - dst_offset = (pPixmap->devPrivate.ptr - info->FB) + - info->fbLocation + pScrn->fbOffset; + dst_offset = (pPixmap->devPrivate.ptr - info->FB); dst_pitch = pPixmap->devKind; } @@ -210,13 +218,21 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv txoffset = pPriv->src_offset; - BEGIN_VIDEO(6); + qwords = info->new_cs ? 8 : 6; + BEGIN_VIDEO(qwords); OUT_VIDEO_REG(R300_TX_FILTER0_0, txfilter); OUT_VIDEO_REG(R300_TX_FILTER1_0, 0); OUT_VIDEO_REG(R300_TX_FORMAT0_0, txformat0); OUT_VIDEO_REG(R300_TX_FORMAT1_0, txformat1); OUT_VIDEO_REG(R300_TX_FORMAT2_0, txpitch); - OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset); + + if (info->new_cs) { + OUT_VIDEO_REG(R300_TX_OFFSET_0, 0); + OUT_RELOC(pPriv->src_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset); + } FINISH_VIDEO(); txenable = R300_TEX_0_ENABLE; @@ -237,13 +253,20 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv R300_TX_MAG_FILTER_NEAREST | (1 << R300_TX_ID_SHIFT)); - BEGIN_VIDEO(6); + qwords = info->new_cs ? 8 : 6; + BEGIN_VIDEO(qwords); OUT_VIDEO_REG(R300_TX_FILTER0_1, txfilter); OUT_VIDEO_REG(R300_TX_FILTER1_1, 0); OUT_VIDEO_REG(R300_TX_FORMAT0_1, txformat0); OUT_VIDEO_REG(R300_TX_FORMAT1_1, txformat1); OUT_VIDEO_REG(R300_TX_FORMAT2_1, txpitch); - OUT_VIDEO_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset); + + if (info->new_cs) { + OUT_VIDEO_REG(R300_TX_OFFSET_1, 0); + OUT_RELOC(pPriv->bicubic_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + OUT_VIDEO_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset); + } FINISH_VIDEO(); /* Enable tex 1 */ @@ -980,11 +1003,18 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv } } - BEGIN_VIDEO(6); + qwords = info->new_cs ? 8 : 6; + BEGIN_VIDEO(qwords); OUT_VIDEO_REG(R300_TX_INVALTAGS, 0); OUT_VIDEO_REG(R300_TX_ENABLE, txenable); - OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset); + if (info->new_cs) { + OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, 0); + OUT_RELOC(dst_bo, 0, RADEON_GEM_DOMAIN_VRAM); + } else { + dst_offset += info->fbLocation + pScrn->fbOffset; + OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset); + } OUT_VIDEO_REG(R300_RB3D_COLORPITCH0, colorpitch); blendcntl = RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO; @@ -1029,6 +1059,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); OUT_VIDEO_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE); + dst_offset += info->fbLocation + pScrn->fbOffset; OUT_VIDEO_REG(RADEON_RB3D_COLOROFFSET, dst_offset); OUT_VIDEO_REG(RADEON_RB3D_COLORPITCH, colorpitch); @@ -1066,7 +1097,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_VIDEO_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32); - OUT_VIDEO_REG(R200_PP_TXOFFSET_0, pPriv->src_offset); + OUT_VIDEO_REG(R200_PP_TXOFFSET_0, pPriv->src_offset + + info->fbLocation + pScrn->fbOffset); OUT_VIDEO_REG(R200_PP_TXCBLEND_0, R200_TXC_ARG_A_ZERO | @@ -1100,7 +1132,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv RADEON_CLAMP_T_CLAMP_LAST | RADEON_YUV_TO_RGB); OUT_VIDEO_REG(RADEON_PP_TXFORMAT_0, txformat); - OUT_VIDEO_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset); + OUT_VIDEO_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset + + info->fbLocation + pScrn->fbOffset); OUT_VIDEO_REG(RADEON_PP_TXCBLEND_0, RADEON_COLOR_ARG_A_ZERO | RADEON_COLOR_ARG_B_ZERO | diff --git a/src/radeon_video.c b/src/radeon_video.c index e71f0f8..aba8884 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -270,7 +270,7 @@ void RADEONInitVideo(ScreenPtr pScreen) memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); adaptors = newAdaptors; - if (!IS_AVIVO_VARIANT) { + if (!IS_AVIVO_VARIANT && !info->drm_mode_setting) { overlayAdaptor = RADEONSetupImageVideo(pScreen); if (overlayAdaptor != NULL) { adaptors[num_adaptors++] = overlayAdaptor; @@ -283,7 +283,7 @@ void RADEONInitVideo(ScreenPtr pScreen) if (info->ChipFamily != CHIP_FAMILY_RV250) { if ((info->ChipFamily < CHIP_FAMILY_RS400) #ifdef XF86DRI - || (info->directRenderingEnabled) + || (info->directRenderingEnabled || info->drm_mode_setting) #endif ) { texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen); @@ -2180,7 +2180,7 @@ RADEONCopyData( #ifdef XF86DRI - if ( info->directRenderingEnabled && info->DMAForXv ) + if ( info->directRenderingEnabled && info->DMAForXv && !info->new_cs ) { uint8_t *buf; uint32_t bufPitch, dstPitchOff; @@ -2443,6 +2443,20 @@ RADEONAllocateMemory( int offset = 0; pScreen = screenInfo.screens[pScrn->scrnIndex]; + + if (info->new_cs) { + dri_bo *video_bo; + + video_bo = dri_bo_alloc(info->bufmgr, "xv pixmap", size, 4096, 0); + + *mem_struct = video_bo; + + if (!video_bo) + return 0; + + return (uint32_t)-1; + + } #ifdef USE_EXA if (info->useEXA) { ExaOffscreenArea *area = *mem_struct; @@ -2516,6 +2530,11 @@ RADEONFreeMemory( ){ RADEONInfoPtr info = RADEONPTR(pScrn); + if (info->new_cs) { + struct dri_bo *bo = mem_struct; + dri_bo_unreference(bo); + return; + } #ifdef USE_EXA if (info->useEXA) { ExaOffscreenArea *area = mem_struct; diff --git a/src/radeon_video.h b/src/radeon_video.h index b9d900d..0687969 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -114,6 +114,9 @@ typedef struct { int src_w, src_h, dst_w, dst_h; int w, h; int drw_x, drw_y; + + dri_bo *src_bo; + dri_bo *bicubic_bo; } RADEONPortPrivRec, *RADEONPortPrivPtr; void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);