#include #include #include #include //#include "xf86.h" #include "uxa/intel.h" #include "i830_reg.h" #include "i965_reg.h" /* bring in brw structs */ #include "brw_defines.h" #include "brw_structs.h" #include "i915_pciids.h" #include #include #define PictOpClear 0 #define PictOpSrc 1 #define PictOpDst 2 #define PictOpOver 3 #define PictOpOverReverse 4 #define PictOpIn 5 #define PictOpInReverse 6 #define PictOpOut 7 #define PictOpOutReverse 8 #define PictOpAtop 9 #define PictOpAtopReverse 10 #define PictOpXor 11 #define PictOpAdd 12 #define PictOpSaturate 13 #define PictOpMaximum 13 static int tls_mask; intel_screen_private *driverPrivate; __LOCK_INIT_RECURSIVE(, __uxa_lock); #define DBG printf typedef struct { struct list entry; uint32_t width; uint32_t height; void *data; uint32_t pitch; drm_intel_bo *bo; uint32_t bo_size; uint32_t flags; }surface_t; #define to_surface(x) (surface_t*)((x)->handle) struct _Pixmap fb_pixmap; struct list sf_list; int uxa_update_fb(struct intel_screen_private *intel); int sna_create_mask() { return 0; }; static void i830_done_composite(PixmapPtr dest) { intel_screen_private *intel = intel_get_screen_private(); if (intel->vertex_flush) intel->vertex_flush(intel); // intel_debug_flush(scrn); } int sna_bitmap_from_handle(bitmap_t *bitmap, uint32_t handle) { struct intel_screen_private *intel = intel_get_screen_private(); drm_intel_bo *bo; surface_t *sf; unsigned int size; bitmap->handle = 0; __lock_acquire_recursive(__uxa_lock); list_for_each_entry(sf, &sf_list, entry) { if (sf->bo->handle == handle) { bitmap->handle = (uint32_t)sf; break; } } __lock_release_recursive(__uxa_lock); if(bitmap->handle) return 0; sf = malloc(sizeof(*sf)); if(sf == NULL) goto err_1; size = bitmap->pitch * bitmap->height; bo = bo_create_from_gem_handle(intel->bufmgr, size, handle); sf->width = bitmap->width; sf->height = bitmap->height; sf->data = NULL; sf->pitch = bitmap->pitch; sf->bo = bo; sf->bo_size = size; sf->flags = bitmap->flags; bitmap->handle = (uint32_t)sf; return 0; err_1: return -1; }; void sna_set_bo_handle(bitmap_t *bitmap, int handle) { sna_bitmap_from_handle(bitmap, handle); }; int sna_blit_tex(bitmap_t *bitmap, bool scale, int dst_x, int dst_y, int w, int h, int src_x, int src_y) { struct _Pixmap pixSrc, pixMask; struct intel_pixmap privSrc; struct _Picture pictSrc, pictDst; struct intel_screen_private *intel = intel_get_screen_private(); surface_t *sf = to_surface(bitmap); int winx, winy; char proc_info[1024]; get_proc_info(proc_info); winx = *(uint32_t*)(proc_info+34); winy = *(uint32_t*)(proc_info+38); memset(&pixSrc, 0, sizeof(pixSrc)); memset(&pixMask, 0, sizeof(pixMask)); memset(&privSrc, 0, sizeof(pixSrc)); memset(&pictSrc, 0, sizeof(pictSrc)); memset(&pictDst, 0, sizeof(pictDst)); pixSrc.drawable.bitsPerPixel = 32; pixSrc.drawable.width = sf->width; pixSrc.drawable.height = sf->height; pixSrc.devKind = sf->pitch; pixSrc.private = &privSrc; list_init(&privSrc.batch); privSrc.bo = sf->bo; privSrc.stride = sf->pitch; privSrc.tiling = I915_TILING_X; pictSrc.format = PICT_x8r8g8b8; pictSrc.filter = PictFilterNearest; pictSrc.repeatType = RepeatNone; pictDst.format = PICT_a8r8g8b8; pictDst.filter = PictFilterNearest; pictDst.repeatType = RepeatNone; uxa_update_fb(intel); // pixDst.drawable.bitsPerPixel = 32; // pixDst.drawable.width = sna_fb.width; // pixDst.drawable.height = sna_fb.height; // pixMask.drawable.bitsPerPixel = 8; // pixMask.drawable.width = update.width; // pixMask.drawable.height = update.height; i965_prepare_composite(PictOpSrc, &pictSrc, NULL, &pictDst, &pixSrc, NULL, &fb_pixmap); i965_composite(&fb_pixmap, src_x, src_y, 0, 0, dst_x, dst_y, w, h); i830_done_composite(&fb_pixmap); intel_batch_submit(); return 0; }; int uxa_init_fb(struct intel_screen_private *intel) { struct drm_i915_fb_info fb; static struct intel_pixmap ipix; int ret; memset(&fb, 0, sizeof(fb)); ret = drmIoctl(intel->scrn, SRV_FBINFO, &fb); if( ret != 0 ) return ret; intel->front_buffer = intel_bo_gem_create_from_name(intel->bufmgr,"frontbuffer", fb.name); if(intel->front_buffer == NULL) return -1; ipix.bo = intel->front_buffer; list_init(&ipix.batch); ipix.stride = fb.pitch; ipix.tiling = fb.tiling; ipix.pinned = PIN_SCANOUT; printf("create frontbuffer name %d bo %x\n", fb.name, ipix.bo); printf("size %d, offset %d handle %d\n",ipix.bo->size, ipix.bo->offset, ipix.bo->handle); fb_pixmap.drawable.bitsPerPixel = 32; fb_pixmap.drawable.width = fb.width; fb_pixmap.drawable.height = fb.height; fb_pixmap.devKind = fb.pitch; fb_pixmap.private = &ipix; return 0; } int uxa_update_fb(struct intel_screen_private *intel) { struct drm_i915_fb_info fb; struct intel_pixmap *ipix; size_t size; int ret; ret = drmIoctl(intel->scrn, SRV_FBINFO, &fb); if( ret != 0 ) return ret; ipix = (struct intel_pixmap*)fb_pixmap.private; ipix->stride = fb.pitch; ipix->tiling = fb.tiling; fb_pixmap.drawable.width = fb.width; fb_pixmap.drawable.height = fb.height; fb_pixmap.devKind = fb.pitch; return 0; }; int uxa_init(uint32_t service) { static struct pci_device device; struct intel_screen_private *intel = intel_get_screen_private(); ioctl_t io; int caps = 0; DBG("%s\n", __FUNCTION__); __lock_acquire_recursive(__uxa_lock); if(intel) goto done; io.handle = service; io.io_code = SRV_GET_PCI_INFO; io.input = &device; io.inp_size = sizeof(device); io.output = NULL; io.out_size = 0; if (call_service(&io)!=0) goto err1; intel = (intel_screen_private*)malloc(sizeof(*intel)); if (intel == NULL) goto err1; list_init(&sf_list); driverPrivate = intel; memset(intel, 0, sizeof(*intel)); // sna->cpu_features = sna_cpu_detect(); intel->PciInfo = &device; intel->info = intel_detect_chipset(intel->PciInfo); intel->scrn = service; intel->bufmgr = intel_bufmgr_gem_init(service, 8192); if(intel->bufmgr == NULL) { printf("Memory manager initialization failed\n"); goto err1; }; if( uxa_init_fb(intel) != 0) goto err1; intel_batch_init(); if (INTEL_INFO(intel)->gen >= 040) gen4_render_state_init(); if (!intel_uxa_init()) { printf("Hardware acceleration initialization failed\n"); goto err1; } tls_mask = tls_alloc(); // printf("tls mask %x\n", tls_mask); done: // caps = sna_device->render.caps; err1: __lock_release_recursive(__uxa_lock); LEAVE(); return caps; } static void gen6_context_switch(intel_screen_private *intel, int new_mode) { intel_batch_submit(intel->scrn); } static void gen5_context_switch(intel_screen_private *intel, int new_mode) { /* Ironlake has a limitation that a 3D or Media command can't * be the first command after a BLT, unless it's * non-pipelined. Instead of trying to track it and emit a * command at the right time, we just emit a dummy * non-pipelined 3D instruction after each blit. */ if (new_mode == I915_EXEC_BLT) { OUT_BATCH(MI_FLUSH | MI_STATE_INSTRUCTION_CACHE_FLUSH | MI_INHIBIT_RENDER_CACHE_FLUSH); } else { OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16); OUT_BATCH(0); } } static void gen4_context_switch(intel_screen_private *intel, int new_mode) { if (new_mode == I915_EXEC_BLT) { OUT_BATCH(MI_FLUSH | MI_STATE_INSTRUCTION_CACHE_FLUSH | MI_INHIBIT_RENDER_CACHE_FLUSH); } } static void intel_limits_init(intel_screen_private *intel) { /* Limits are described in the BLT engine chapter under Graphics Data Size * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO, * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO. * * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768. * * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled. * i965 limits 3D surface to 4kB-aligned offset if tiled. * i965 limits 3D surfaces to w,h of ?,8192. * i965 limits 3D surface to pitch of 1B - 128kB. * i965 limits 3D surface pitch alignment to 1 or 2 times the element size. * i965 limits 3D surface pitch alignment to 512B if tiled. * i965 limits 3D destination drawing rect to w,h of 8192,8192. * * i915 limits 3D textures to 4B-aligned offset if un-tiled. * i915 limits 3D textures to ~4kB-aligned offset if tiled. * i915 limits 3D textures to width,height of 2048,2048. * i915 limits 3D textures to pitch of 16B - 8kB, in dwords. * i915 limits 3D destination to ~4kB-aligned offset if tiled. * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled. * i915 limits 3D destination to pitch 64B-aligned if used with depth. * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled. * i915 limits 3D destination to POT aligned pitch if tiled. * i915 limits 3D destination drawing rect to w,h of 2048,2048. * * i845 limits 3D textures to 4B-aligned offset if un-tiled. * i845 limits 3D textures to ~4kB-aligned offset if tiled. * i845 limits 3D textures to width,height of 2048,2048. * i845 limits 3D textures to pitch of 4B - 8kB, in dwords. * i845 limits 3D destination to 4B-aligned offset if un-tiled. * i845 limits 3D destination to ~4kB-aligned offset if tiled. * i845 limits 3D destination to pitch of 8B - 8kB, in dwords. * i845 limits 3D destination drawing rect to w,h of 2048,2048. * * For the tiled issues, the only tiled buffer we draw to should be * the front, which will have an appropriate pitch/offset already set up, * so UXA doesn't need to worry. */ if (INTEL_INFO(intel)->gen >= 040) { intel->accel_pixmap_offset_alignment = 4 * 2; intel->accel_max_x = 8192; intel->accel_max_y = 8192; } else { intel->accel_pixmap_offset_alignment = 4; intel->accel_max_x = 2048; intel->accel_max_y = 2048; } } Bool intel_uxa_init() { intel_screen_private *intel = intel_get_screen_private(); intel_limits_init(intel); intel->prim_offset = 0; intel->vertex_count = 0; intel->vertex_offset = 0; intel->vertex_used = 0; intel->floats_per_vertex = 0; intel->last_floats_per_vertex = 0; intel->vertex_bo = NULL; intel->surface_used = 0; intel->surface_reloc = 0; /* intel->uxa_driver->check_composite = i965_check_composite; intel->uxa_driver->check_composite_texture = i965_check_composite_texture; intel->uxa_driver->prepare_composite = i965_prepare_composite; intel->uxa_driver->composite = i965_composite; intel->uxa_driver->done_composite = i830_done_composite; */ intel->vertex_flush = i965_vertex_flush; intel->batch_flush = i965_batch_flush; intel->batch_commit_notify = i965_batch_commit_notify; if (IS_GEN4(intel)) { intel->context_switch = gen4_context_switch; } else if (IS_GEN5(intel)) { intel->context_switch = gen5_context_switch; } else { intel->context_switch = gen6_context_switch; } return TRUE; } static const struct intel_device_info intel_generic_info = { .gen = -1, }; static const struct intel_device_info intel_i915_info = { .gen = 030, }; static const struct intel_device_info intel_i945_info = { .gen = 031, }; static const struct intel_device_info intel_g33_info = { .gen = 033, }; static const struct intel_device_info intel_i965_info = { .gen = 040, }; static const struct intel_device_info intel_g4x_info = { .gen = 045, }; static const struct intel_device_info intel_ironlake_info = { .gen = 050, }; static const struct intel_device_info intel_sandybridge_info = { .gen = 060, }; static const struct intel_device_info intel_ivybridge_info = { .gen = 070, }; static const struct intel_device_info intel_valleyview_info = { .gen = 071, }; static const struct intel_device_info intel_haswell_info = { .gen = 075, }; #define INTEL_DEVICE_MATCH(d,i) \ { 0x8086, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0x3 << 16, 0xff << 16, (intptr_t)(i) } static const struct pci_id_match intel_device_match[] = { INTEL_I915G_IDS(&intel_i915_info), INTEL_I915GM_IDS(&intel_i915_info), INTEL_I945G_IDS(&intel_i945_info), INTEL_I945GM_IDS(&intel_i945_info), INTEL_G33_IDS(&intel_g33_info), INTEL_PINEVIEW_IDS(&intel_g33_info), INTEL_I965G_IDS(&intel_i965_info), INTEL_I965GM_IDS(&intel_i965_info), INTEL_G45_IDS(&intel_g4x_info), INTEL_GM45_IDS(&intel_g4x_info), INTEL_IRONLAKE_D_IDS(&intel_ironlake_info), INTEL_IRONLAKE_M_IDS(&intel_ironlake_info), INTEL_SNB_D_IDS(&intel_sandybridge_info), INTEL_SNB_M_IDS(&intel_sandybridge_info), INTEL_IVB_D_IDS(&intel_ivybridge_info), INTEL_IVB_M_IDS(&intel_ivybridge_info), INTEL_HSW_D_IDS(&intel_haswell_info), INTEL_HSW_M_IDS(&intel_haswell_info), INTEL_VLV_D_IDS(&intel_valleyview_info), INTEL_VLV_M_IDS(&intel_valleyview_info), INTEL_VGA_DEVICE(PCI_MATCH_ANY, &intel_generic_info), { 0, 0, 0 }, }; const struct pci_id_match *PciDevMatch(uint16_t dev,const struct pci_id_match *list) { while(list->device_id) { if(dev==list->device_id) return list; list++; } return NULL; } const struct intel_device_info * intel_detect_chipset(struct pci_device *pci) { const struct pci_id_match *ent = NULL; ent = PciDevMatch(pci->device_id, intel_device_match); if(ent != NULL) return (const struct intel_device_info*)ent->match_data; else return &intel_generic_info; }