Subversion Repositories Kolibri OS

Rev

Rev 2340 | Rev 2344 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. #define iowrite32(v, addr)      writel((v), (addr))
  3.  
  4. #include "drmP.h"
  5. #include "drm.h"
  6. #include "i915_drm.h"
  7. #include "i915_drv.h"
  8. #include "intel_drv.h"
  9.  
  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <linux/mod_devicetable.h>
  13. #include <errno-base.h>
  14. #include <linux/pci.h>
  15.  
  16. #include <syscall.h>
  17.  
  18. #include "bitmap.h"
  19.  
  20.  
  21. typedef struct
  22. {
  23.     kobj_t     header;
  24.  
  25.     uint32_t  *data;
  26.     uint32_t   hot_x;
  27.     uint32_t   hot_y;
  28.  
  29.     struct list_head   list;
  30.     struct drm_i915_gem_object  *cobj;
  31. }cursor_t;
  32.  
  33. #define CURSOR_WIDTH 64
  34. #define CURSOR_HEIGHT 64
  35.  
  36.  
  37. struct tag_display
  38. {
  39.     int  x;
  40.     int  y;
  41.     int  width;
  42.     int  height;
  43.     int  bpp;
  44.     int  vrefresh;
  45.     int  pitch;
  46.     int  lfb;
  47.  
  48.     int  supported_modes;
  49.     struct drm_device    *ddev;
  50.     struct drm_connector *connector;
  51.     struct drm_crtc      *crtc;
  52.  
  53.     struct list_head   cursors;
  54.  
  55.     cursor_t   *cursor;
  56.     int       (*init_cursor)(cursor_t*);
  57.     cursor_t* (__stdcall *select_cursor)(cursor_t*);
  58.     void      (*show_cursor)(int show);
  59.     void      (__stdcall *move_cursor)(cursor_t *cursor, int x, int y);
  60.     void      (__stdcall *restore_cursor)(int x, int y);
  61.     void      (*disable_mouse)(void);
  62. };
  63.  
  64.  
  65. static display_t *os_display;
  66.  
  67. u32_t cmd_buffer;
  68. u32_t cmd_offset;
  69.  
  70. int init_cursor(cursor_t *cursor);
  71. static cursor_t*  __stdcall select_cursor_kms(cursor_t *cursor);
  72. static void       __stdcall move_cursor_kms(cursor_t *cursor, int x, int y);
  73.  
  74. void __stdcall restore_cursor(int x, int y)
  75. {};
  76.  
  77. void disable_mouse(void)
  78. {};
  79.  
  80. static int count_connector_modes(struct drm_connector* connector)
  81. {
  82.     struct drm_display_mode  *mode;
  83.     int count = 0;
  84.  
  85.     list_for_each_entry(mode, &connector->modes, head)
  86.     {
  87.         count++;
  88.     };
  89.     return count;
  90. };
  91.  
  92. int init_display_kms(struct drm_device *dev)
  93. {
  94.     struct drm_connector    *connector;
  95.     struct drm_connector_helper_funcs *connector_funcs;
  96.     struct drm_encoder      *encoder;
  97.     struct drm_crtc         *crtc = NULL;
  98.     struct drm_framebuffer  *fb;
  99.  
  100.     cursor_t  *cursor;
  101.     u32_t      ifl;
  102.  
  103.     ENTER();
  104.  
  105.     list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  106.     {
  107.         if( connector->status != connector_status_connected)
  108.             continue;
  109.  
  110.         connector_funcs = connector->helper_private;
  111.         encoder = connector_funcs->best_encoder(connector);
  112.         if( encoder == NULL)
  113.         {
  114.             dbgprintf("CONNECTOR %x ID: %d no active encoders\n",
  115.                       connector, connector->base.id);
  116.             continue;
  117.         }
  118.         connector->encoder = encoder;
  119.  
  120.         dbgprintf("CONNECTOR %x ID:  %d status %d encoder %x\n crtc %x\n",
  121.                connector, connector->base.id,
  122.                connector->status, connector->encoder,
  123.                encoder->crtc);
  124.  
  125.         crtc = encoder->crtc;
  126.         break;
  127.     };
  128.  
  129.     if(connector == NULL)
  130.     {
  131.         dbgprintf("No active connectors!\n");
  132.         return -1;
  133.     };
  134.  
  135.     if(crtc == NULL)
  136.     {
  137.         struct drm_crtc *tmp_crtc;
  138.         int crtc_mask = 1;
  139.  
  140.         list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head)
  141.         {
  142.             if (encoder->possible_crtcs & crtc_mask)
  143.             {
  144.                 crtc = tmp_crtc;
  145.                 encoder->crtc = crtc;
  146.                 break;
  147.             };
  148.             crtc_mask <<= 1;
  149.         };
  150.     };
  151.  
  152.     if(crtc == NULL)
  153.     {
  154.         dbgprintf("No CRTC for encoder %d\n", encoder->base.id);
  155.         return -1;
  156.     };
  157.  
  158.  
  159.     DRM_DEBUG_KMS("[Select CRTC:%d]\n", crtc->base.id);
  160.  
  161.     os_display = GetDisplay();
  162.  
  163.     os_display->ddev = dev;
  164.     os_display->connector = connector;
  165.     os_display->crtc = crtc;
  166.  
  167.     os_display->supported_modes = count_connector_modes(connector);
  168.  
  169.  
  170.     ifl = safe_cli();
  171.     {
  172.         struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  173.  
  174.         list_for_each_entry(cursor, &os_display->cursors, list)
  175.         {
  176.             init_cursor(cursor);
  177.         };
  178.  
  179.         os_display->restore_cursor(0,0);
  180.         os_display->init_cursor    = init_cursor;
  181.         os_display->select_cursor  = select_cursor_kms;
  182.         os_display->show_cursor    = NULL;
  183.         os_display->move_cursor    = move_cursor_kms;
  184.         os_display->restore_cursor = restore_cursor;
  185.         os_display->disable_mouse  = disable_mouse;
  186.  
  187.         intel_crtc->cursor_x = os_display->width/2;
  188.         intel_crtc->cursor_y = os_display->height/2;
  189.  
  190.         select_cursor_kms(os_display->cursor);
  191.     };
  192.     safe_sti(ifl);
  193.  
  194. #define XY_COLOR_BLT        ((2<<29)|(0x50<<22)|(0x4))
  195. #define BLT_WRITE_ALPHA     (1<<21)
  196. #define BLT_WRITE_RGB       (1<<20)
  197.  
  198. #if 1
  199.     {
  200.  
  201.         drm_i915_private_t *dev_priv = dev->dev_private;
  202.         struct drm_i915_gem_object *obj;
  203.         struct intel_ring_buffer *ring;
  204.  
  205.         obj = i915_gem_alloc_object(dev, 4096);
  206.         i915_gem_object_pin(obj, 4096, true);
  207.  
  208.         cmd_buffer = MapIoMem(obj->pages[0], 4096, PG_SW|PG_NOCACHE);
  209.         cmd_offset = obj->gtt_offset;
  210.     };
  211. #endif
  212.  
  213.     int err;
  214.  
  215.     err = init_bitmaps();
  216.     if( !err )
  217.     {
  218.         printf("Initialize bitmap manager\n");
  219.     };
  220.  
  221.     LEAVE();
  222.  
  223.     return 0;
  224. };
  225.  
  226.  
  227. bool set_mode(struct drm_device *dev, struct drm_connector *connector,
  228.               videomode_t *reqmode, bool strict)
  229. {
  230.     struct drm_display_mode  *mode = NULL, *tmpmode;
  231.     drm_i915_private_t *dev_priv = dev->dev_private;
  232.     struct drm_fb_helper *fb_helper = &dev_priv->fbdev->helper;
  233.  
  234.     bool ret = false;
  235.  
  236.     ENTER();
  237.  
  238.     dbgprintf("width %d height %d vrefresh %d\n",
  239.                reqmode->width, reqmode->height, reqmode->freq);
  240.  
  241.     list_for_each_entry(tmpmode, &connector->modes, head)
  242.     {
  243.         if( (drm_mode_width(tmpmode)    == reqmode->width)  &&
  244.             (drm_mode_height(tmpmode)   == reqmode->height) &&
  245.             (drm_mode_vrefresh(tmpmode) == reqmode->freq) )
  246.         {
  247.             mode = tmpmode;
  248.             goto do_set;
  249.         }
  250.     };
  251.  
  252.     if( (mode == NULL) && (strict == false) )
  253.     {
  254.         list_for_each_entry(tmpmode, &connector->modes, head)
  255.         {
  256.             if( (drm_mode_width(tmpmode)  == reqmode->width)  &&
  257.                 (drm_mode_height(tmpmode) == reqmode->height) )
  258.             {
  259.                 mode = tmpmode;
  260.                 goto do_set;
  261.             }
  262.         };
  263.     };
  264.  
  265. do_set:
  266.  
  267.     if( mode != NULL )
  268.     {
  269.         struct drm_framebuffer   *fb;
  270.         struct drm_encoder       *encoder;
  271.         struct drm_crtc          *crtc;
  272.  
  273.         char *con_name;
  274.         char *enc_name;
  275.  
  276.         encoder = connector->encoder;
  277.         crtc = encoder->crtc;
  278.  
  279.         con_name = drm_get_connector_name(connector);
  280.         enc_name = drm_get_encoder_name(encoder);
  281.  
  282.         dbgprintf("set mode %d %d connector %s encoder %s\n",
  283.                    reqmode->width, reqmode->height, con_name, enc_name);
  284.  
  285.         fb = fb_helper->fb;
  286.  
  287.         fb->width  = reqmode->width;
  288.         fb->height = reqmode->height;
  289.         fb->pitches[0]  = ALIGN(reqmode->width * 4, 64);
  290.         fb->pitches[1]  = ALIGN(reqmode->width * 4, 64);
  291.         fb->pitches[2]  = ALIGN(reqmode->width * 4, 64);
  292.         fb->pitches[3]  = ALIGN(reqmode->width * 4, 64);
  293.  
  294.         fb->bits_per_pixel = 32;
  295.         fb->depth == 24;
  296.  
  297.         crtc->fb = fb;
  298.         crtc->enabled = true;
  299.         os_display->crtc = crtc;
  300.  
  301.         ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
  302.  
  303. //        select_cursor_kms(rdisplay->cursor);
  304. //        radeon_show_cursor_kms(crtc);
  305.  
  306.         if (ret == true)
  307.         {
  308.             os_display->width    = fb->width;
  309.             os_display->height   = fb->height;
  310.             os_display->pitch    = fb->pitches[0];
  311.             os_display->vrefresh = drm_mode_vrefresh(mode);
  312.  
  313.             sysSetScreen(fb->width, fb->height, fb->pitches[0]);
  314.  
  315.             dbgprintf("new mode %d x %d pitch %d\n",
  316.                        fb->width, fb->height, fb->pitches[0]);
  317.         }
  318.         else
  319.             DRM_ERROR("failed to set mode %d_%d on crtc %p\n",
  320.                        fb->width, fb->height, crtc);
  321.     }
  322.  
  323.     LEAVE();
  324.     return ret;
  325. };
  326.  
  327.  
  328.  
  329. int get_videomodes(videomode_t *mode, int *count)
  330. {
  331.     int err = -1;
  332.  
  333.     ENTER();
  334.  
  335.     dbgprintf("mode %x count %d\n", mode, *count);
  336.  
  337.     if( *count == 0 )
  338.     {
  339.         *count = os_display->supported_modes;
  340.         err = 0;
  341.     }
  342.     else if( mode != NULL )
  343.     {
  344.         struct drm_display_mode  *drmmode;
  345.         int i = 0;
  346.  
  347.         if( *count > os_display->supported_modes)
  348.             *count = os_display->supported_modes;
  349.  
  350.         list_for_each_entry(drmmode, &os_display->connector->modes, head)
  351.         {
  352.             if( i < *count)
  353.             {
  354.                 mode->width  = drm_mode_width(drmmode);
  355.                 mode->height = drm_mode_height(drmmode);
  356.                 mode->bpp    = 32;
  357.                 mode->freq   = drm_mode_vrefresh(drmmode);
  358.                 i++;
  359.                 mode++;
  360.             }
  361.             else break;
  362.         };
  363.         *count = i;
  364.         err = 0;
  365.     };
  366.     LEAVE();
  367.     return err;
  368. };
  369.  
  370. int set_user_mode(videomode_t *mode)
  371. {
  372.     int err = -1;
  373.  
  374.     ENTER();
  375.  
  376.     dbgprintf("width %d height %d vrefresh %d\n",
  377.                mode->width, mode->height, mode->freq);
  378.  
  379.     if( (mode->width  != 0)  &&
  380.         (mode->height != 0)  &&
  381.         (mode->freq   != 0 ) &&
  382.         ( (mode->width   != os_display->width)  ||
  383.           (mode->height  != os_display->height) ||
  384.           (mode->freq    != os_display->vrefresh) ) )
  385.     {
  386.         if( set_mode(os_display->ddev, os_display->connector, mode, true) )
  387.             err = 0;
  388.     };
  389.  
  390.     LEAVE();
  391.     return err;
  392. };
  393.  
  394. void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor)
  395. {
  396. /*  FIXME    synchronization */
  397.  
  398.     list_del(&cursor->list);
  399. //    radeon_bo_unpin(cursor->robj);
  400. //    KernelFree(cursor->data);
  401.     __DestroyObject(cursor);
  402. };
  403.  
  404. int init_cursor(cursor_t *cursor)
  405. {
  406.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  407.     struct drm_i915_gem_object *obj;
  408.     uint32_t *bits;
  409.     uint32_t *src;
  410.  
  411.     int       i,j;
  412.     int       ret;
  413.  
  414.     ENTER();
  415.  
  416.     if (dev_priv->info->cursor_needs_physical)
  417.     {
  418.         bits = (uint32_t*)KernelAlloc(CURSOR_WIDTH*CURSOR_HEIGHT*4);
  419.         if (unlikely(bits == NULL))
  420.             return ENOMEM;
  421.         cursor->cobj = (struct drm_i915_gem_object *)GetPgAddr(bits);
  422.     }
  423.     else
  424.     {
  425.         obj = i915_gem_alloc_object(os_display->ddev, CURSOR_WIDTH*CURSOR_HEIGHT*4);
  426.         if (unlikely(obj == NULL))
  427.             return -ENOMEM;
  428.  
  429.         ret = i915_gem_object_pin(obj, CURSOR_WIDTH*CURSOR_HEIGHT*4, true);
  430.         if (ret) {
  431. //           drm_gem_object_unreference(&obj->base);
  432.             return ret;
  433.         }
  434.  
  435. /* You don't need to worry about fragmentation issues.
  436.  * GTT space is continuous. I guarantee it.                           */
  437.  
  438.         bits = (u32*)MapIoMem(get_bus_addr() + obj->gtt_offset,
  439.                     CURSOR_WIDTH*CURSOR_HEIGHT*4, PG_SW);
  440.  
  441.         if (unlikely(bits == NULL))
  442.         {
  443. //          i915_gem_object_unpin(obj);
  444. //           drm_gem_object_unreference(&obj->base);
  445.             return -ENOMEM;
  446.         };
  447.         cursor->cobj = obj;
  448.     };
  449.  
  450.     src = cursor->data;
  451.  
  452.     for(i = 0; i < 32; i++)
  453.     {
  454.         for(j = 0; j < 32; j++)
  455.             *bits++ = *src++;
  456.         for(j = 32; j < CURSOR_WIDTH; j++)
  457.             *bits++ = 0;
  458.     }
  459.     for(i = 0; i < CURSOR_WIDTH*(CURSOR_HEIGHT-32); i++)
  460.         *bits++ = 0;
  461.  
  462. // release old cursor
  463.  
  464.     KernelFree(cursor->data);
  465.  
  466.     cursor->data = bits;
  467.  
  468.     cursor->header.destroy = destroy_cursor;
  469.     LEAVE();
  470.  
  471.     return 0;
  472. }
  473.  
  474.  
  475. static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
  476. {
  477.     struct drm_device *dev = crtc->dev;
  478.     struct drm_i915_private *dev_priv = dev->dev_private;
  479.     struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  480.     int pipe = intel_crtc->pipe;
  481.     bool visible = base != 0;
  482.  
  483.     if (intel_crtc->cursor_visible != visible) {
  484.         uint32_t cntl = I915_READ(CURCNTR(pipe));
  485.         if (base) {
  486.             cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
  487.             cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
  488.             cntl |= pipe << 28; /* Connect to correct pipe */
  489.         } else {
  490.             cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
  491.             cntl |= CURSOR_MODE_DISABLE;
  492.         }
  493.         I915_WRITE(CURCNTR(pipe), cntl);
  494.  
  495.         intel_crtc->cursor_visible = visible;
  496.     }
  497.     /* and commit changes on next vblank */
  498.     I915_WRITE(CURBASE(pipe), base);
  499. }
  500.  
  501. void __stdcall move_cursor_kms(cursor_t *cursor, int x, int y)
  502. {
  503.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  504.     struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  505.     u32 base, pos;
  506.     bool visible;
  507.  
  508.     int pipe = intel_crtc->pipe;
  509.  
  510.     intel_crtc->cursor_x = x;
  511.     intel_crtc->cursor_y = y;
  512.  
  513.     x = x - cursor->hot_x;
  514.     y = y - cursor->hot_y;
  515.  
  516.  
  517.     pos = 0;
  518.  
  519.     base = intel_crtc->cursor_addr;
  520.     if (x >= os_display->width)
  521.         base = 0;
  522.  
  523.     if (y >= os_display->height)
  524.         base = 0;
  525.  
  526.     if (x < 0)
  527.     {
  528.         if (x + intel_crtc->cursor_width < 0)
  529.             base = 0;
  530.  
  531.         pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
  532.         x = -x;
  533.     }
  534.     pos |= x << CURSOR_X_SHIFT;
  535.  
  536.     if (y < 0)
  537.     {
  538.         if (y + intel_crtc->cursor_height < 0)
  539.             base = 0;
  540.  
  541.         pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
  542.         y = -y;
  543.     }
  544.     pos |= y << CURSOR_Y_SHIFT;
  545.  
  546.     visible = base != 0;
  547.     if (!visible && !intel_crtc->cursor_visible)
  548.         return;
  549.  
  550.     I915_WRITE(CURPOS(pipe), pos);
  551. //    if (IS_845G(dev) || IS_I865G(dev))
  552. //        i845_update_cursor(crtc, base);
  553. //    else
  554.         i9xx_update_cursor(os_display->crtc, base);
  555.  
  556. };
  557.  
  558.  
  559. cursor_t* __stdcall select_cursor_kms(cursor_t *cursor)
  560. {
  561.     struct drm_i915_private *dev_priv = os_display->ddev->dev_private;
  562.     struct intel_crtc *intel_crtc = to_intel_crtc(os_display->crtc);
  563.     cursor_t *old;
  564.  
  565.     old = os_display->cursor;
  566.     os_display->cursor = cursor;
  567.  
  568.     if (!dev_priv->info->cursor_needs_physical)
  569.        intel_crtc->cursor_addr = cursor->cobj->gtt_offset;
  570.     else
  571.         intel_crtc->cursor_addr = cursor->cobj;
  572.  
  573.     intel_crtc->cursor_width = 32;
  574.     intel_crtc->cursor_height = 32;
  575.  
  576.     move_cursor_kms(cursor, intel_crtc->cursor_x, intel_crtc->cursor_y);
  577.     return old;
  578. };
  579.  
  580. extern struct drm_device *main_device;
  581.  
  582. #define XY_SRC_COPY_BLT_CMD     ((2<<29)|(0x53<<22)|6)
  583.  
  584.  
  585. typedef struct
  586. {
  587.     int left;
  588.     int top;
  589.     int right;
  590.     int bottom;
  591. }rect_t;
  592.  
  593.  
  594. #include "clip.inc"
  595.  
  596. void  FASTCALL GetWindowRect(rect_t *rc)__asm__("GetWindowRect");
  597.  
  598. #define CURRENT_TASK             (0x80003000)
  599.  
  600. static u32_t get_display_map()
  601. {
  602.     u32_t   addr;
  603.  
  604.     addr = (u32_t)os_display;
  605.     addr+= sizeof(display_t);            /*  shoot me  */
  606.     return *(u32_t*)addr;
  607. }
  608.  
  609. #define XY_SRC_COPY_CHROMA_CMD     ((2<<29)|(0x73<<22)|8)
  610. #define ROP_COPY_SRC               0xCC
  611. #define FORMAT8888                 3
  612.  
  613. typedef int v4si __attribute__ ((vector_size (16)));
  614.  
  615.  
  616. int blit_video(u32 hbitmap, int  dst_x, int dst_y,
  617.                int src_x, int src_y, u32 w, u32 h)
  618. {
  619.     drm_i915_private_t *dev_priv = main_device->dev_private;
  620.     struct intel_ring_buffer *ring;
  621.  
  622.     bitmap_t  *bitmap;
  623.     rect_t     winrc;
  624.     clip_t     dst_clip;
  625.     clip_t     src_clip;
  626.     u32_t      width;
  627.     u32_t      height;
  628.  
  629.     u32_t      br13, cmd, slot_mask, *b;
  630.     u32_t      offset;
  631.     u8         slot;
  632.     int      n=0;
  633.  
  634.     if(unlikely(hbitmap==0))
  635.         return -1;
  636.  
  637.     bitmap = (bitmap_t*)hman_get_data(&bm_man, hbitmap);
  638.  
  639.     if(unlikely(bitmap==NULL))
  640.         return -1;
  641.  
  642.  
  643.     GetWindowRect(&winrc);
  644.  
  645.     dst_clip.xmin   = 0;
  646.     dst_clip.ymin   = 0;
  647.     dst_clip.xmax   = winrc.right-winrc.left-1;
  648.     dst_clip.ymax   = winrc.bottom -winrc.top -1;
  649.  
  650.     src_clip.xmin   = 0;
  651.     src_clip.ymin   = 0;
  652.     src_clip.xmax   = bitmap->width  - 1;
  653.     src_clip.ymax   = bitmap->height - 1;
  654.  
  655.     width  = w;
  656.     height = h;
  657.  
  658.     if( blit_clip(&dst_clip, &dst_x, &dst_y,
  659.                   &src_clip, &src_x, &src_y,
  660.                   &width, &height) )
  661.         return 0;
  662.  
  663.     dst_x+= winrc.left;
  664.     dst_y+= winrc.top;
  665.  
  666.     slot = *((u8*)CURRENT_TASK);
  667.  
  668.     slot_mask = (u32_t)slot<<24;
  669.  
  670.     {
  671. #if 0
  672.         static v4si write_mask = {0xFF000000, 0xFF000000,
  673.                                   0xFF000000, 0xFF000000};
  674.  
  675.         u8* src_offset;
  676.         u8* dst_offset;
  677.  
  678.         src_offset = (u8*)(src_y*bitmap->pitch + src_x*4);
  679.         src_offset += (u32)bitmap->uaddr;
  680.  
  681.         dst_offset = (u8*)(dst_y*os_display->width + dst_x);
  682.         dst_offset+= get_display_map();
  683.  
  684.         u32_t tmp_h = height;
  685.  
  686.         __asm__ __volatile__ (
  687.         "movdqa     %[write_mask],  %%xmm7    \n"
  688.         "movd       %[slot_mask],   %%xmm6    \n"
  689.         "punpckldq  %%xmm6, %%xmm6            \n"
  690.         "punpcklqdq %%xmm6, %%xmm6            \n"
  691.         :: [write_mask] "m" (write_mask),
  692.            [slot_mask]  "g" (slot_mask)
  693.         :"xmm7", "xmm6");
  694.  
  695.         while( tmp_h--)
  696.         {
  697.             u32_t tmp_w = width;
  698.  
  699.             u8* tmp_src = src_offset;
  700.             u8* tmp_dst = dst_offset;
  701.  
  702.             src_offset+= bitmap->pitch;
  703.             dst_offset+= os_display->width;
  704.  
  705.             while( tmp_w >= 8 )
  706.             {
  707.                 __asm__ __volatile__ (
  708.                 "movq       (%0),   %%xmm0            \n"
  709.                 "punpcklbw  %%xmm0, %%xmm0            \n"
  710.                 "movdqa     %%xmm0, %%xmm1            \n"
  711.                 "punpcklwd  %%xmm0, %%xmm0            \n"
  712.                 "punpckhwd  %%xmm1, %%xmm1            \n"
  713.                 "pcmpeqb    %%xmm6, %%xmm0            \n"
  714.                 "pcmpeqb    %%xmm6, %%xmm1            \n"
  715.                 "maskmovdqu %%xmm7, %%xmm0            \n"
  716.                 "addl       $16, %%edi                \n"
  717.                 "maskmovdqu %%xmm7, %%xmm1            \n"
  718.                 :: "r" (tmp_dst), "D" (tmp_src)
  719.                 :"xmm0", "xmm1");
  720.                 __asm__ __volatile__ ("":::"edi");
  721.                 tmp_w -= 8;
  722.                 tmp_src += 32;
  723.                 tmp_dst += 8;
  724.             };
  725.  
  726.             if( tmp_w >= 4 )
  727.             {
  728.                 __asm__ __volatile__ (
  729.                 "movd       (%0),   %%xmm0            \n"
  730.                 "punpcklbw  %%xmm0, %%xmm0            \n"
  731.                 "punpcklwd  %%xmm0, %%xmm0            \n"
  732.                 "pcmpeqb    %%xmm6, %%xmm0            \n"
  733.                 "maskmovdqu %%xmm7, %%xmm0            \n"
  734.                 :: "r" (tmp_dst), "D" (tmp_src)
  735.                 :"xmm0");
  736.                 tmp_w -= 4;
  737.                 tmp_src += 16;
  738.                 tmp_dst += 4;
  739.             };
  740.  
  741.             while( tmp_w--)
  742.             {
  743.                 *(tmp_src+3) = (*tmp_dst==slot)?0xFF:0x00;
  744.                 tmp_src+=4;
  745.                 tmp_dst++;
  746.             };
  747.         };
  748. #else
  749.         u8* src_offset;
  750.         u8* dst_offset;
  751.  
  752.         src_offset = (u8*)(src_y*bitmap->pitch + src_x*4);
  753.         src_offset += (u32)bitmap->uaddr;
  754.  
  755.         dst_offset = (u8*)(dst_y*os_display->width + dst_x);
  756.         dst_offset+= get_display_map();
  757.  
  758.         u32_t tmp_h = height;
  759.  
  760.         while( tmp_h--)
  761.         {
  762.             u32_t tmp_w = width;
  763.  
  764.             u8* tmp_src = src_offset;
  765.             u8* tmp_dst = dst_offset;
  766.  
  767.             src_offset+= bitmap->pitch;
  768.             dst_offset+= os_display->width;
  769.  
  770.             while( tmp_w--)
  771.             {
  772.                 *(tmp_src+3) = (*tmp_dst==slot)?0xFF:0x00;
  773.                 tmp_src+=4;
  774.                 tmp_dst++;
  775.             };
  776.         };
  777.     }
  778. #endif
  779.  
  780.     if((cmd_buffer & 0xFC0)==0xFC0)
  781.         cmd_buffer&= 0xFFFFF000;
  782.  
  783.     b = (u32_t*)ALIGN(cmd_buffer,16);
  784.  
  785.     offset = cmd_offset + ((u32_t)b & 0xFFF);
  786.  
  787.     cmd = XY_SRC_COPY_CHROMA_CMD | BLT_WRITE_RGB | BLT_WRITE_ALPHA;
  788.     cmd |= 3 << 17;
  789.  
  790.     br13 = os_display->pitch;
  791.     br13|= ROP_COPY_SRC << 16;
  792.     br13|= FORMAT8888   << 24;
  793.  
  794.     b[n++] = cmd;
  795.     b[n++] = br13;
  796.     b[n++] = (dst_y << 16) | dst_x;                   // left, top
  797.     b[n++] = ((dst_y+height-1)<< 16)|(dst_x+width-1); // bottom, right
  798.     b[n++] = 0;                          // destination
  799.     b[n++] = (src_y << 16) | src_x;      // source left & top
  800.     b[n++] = bitmap->pitch;              // source pitch
  801.     b[n++] = bitmap->gaddr;              // source
  802.  
  803.     b[n++] = 0;                          // Transparency Color Low
  804.     b[n++] = 0x00FFFFFF;                 // Transparency Color High
  805.  
  806.     b[n++] = MI_BATCH_BUFFER_END;
  807.     if( n & 1)
  808.         b[n++] = MI_NOOP;
  809.  
  810. //    i915_gem_object_set_to_gtt_domain(obj, false);
  811.  
  812.     if (HAS_BLT(main_device))
  813.         ring = &dev_priv->ring[BCS];
  814.     else
  815.         ring = &dev_priv->ring[RCS];
  816.  
  817.     ring->dispatch_execbuffer(ring, cmd_offset, n*4);
  818.  
  819.     intel_ring_begin(ring, 4);
  820. //    if (ret)
  821. //        return ret;
  822.  
  823.     intel_ring_emit(ring, MI_FLUSH_DW);
  824.     intel_ring_emit(ring, 0);
  825.     intel_ring_emit(ring, 0);
  826.     intel_ring_emit(ring, MI_NOOP);
  827.     intel_ring_advance(ring);
  828.  
  829.     return 0;
  830. fail:
  831.     return -1;
  832. };
  833.