91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux framebuffer雙緩沖防止閃爍

發布時間:2020-07-25 23:54:03 來源:網絡 閱讀:795 作者:qq老李說事 欄目:開發技術

  使用Linux Framebuffer繪制32位真彩圖形:

  并發了朋友圈表示這件事結束了,玩了一天,玩惡心了。

  但是我依然是想做出一個可以拖拽的不規則GUI界面(用皮鞋或者小小的照片做界面輪廓)來的。所以半夜就爬起來繼續折騰。

  無奈,沒有找到獲取鼠標焦點的好方法,都太復雜,要知道,我是希望在framebuffer上玩啊,不希望依賴那些已經集成在GUI里面的東西。

  我不就想模擬個拖拽嘛,簡單,用線程控制圖片在屏幕上漂移,即:

  // setPoint方法已經抽象獨立了出來,成為一個static方法,以免main函數太長。

  while(true) {

  setPoint(width, height, xoffset%200, yoffset%50);

  try {

  Thread.sleep(100);

  } catch (InterruptedException e) { }

  xoffset += 2;

  yoffset += 2;

  }

  這個代碼測試下來, 閃爍太厲害了! 根本就沒法看:

  怎么辦?如果簡單的圖片漂移都這么閃爍,那如果鼠標拖拽移動圖片,結局注定令人遺憾。怎么辦?

  找根源!根源就是 畫圖的時間太久了! 我可是一個像素一個像素畫的啊!

  當然了,我知道,如果Java通過JNI將一個像素數組傳遞到本地代碼,然后本地代碼直接 memcpy,那將是令人賽里布瑞特的。可是我并不知道如何從Java往本地代碼傳遞大數組…另外,我注意是想把事情做純粹些。 我不想把事情交給庫去解決,我要自己解決! (可能賺錢的經理們又要笑我了,但我就是這樣,鄙視業務邏輯。)

  利用雙緩沖來解決問題。

  意思就是說, 逐像素點畫圖這件耗時的操作,不要直接操作顯存,而是操作一塊預先分配好的和顯存一樣大小的緩沖區,等逐點畫圖完成之后,一次性將該緩沖區的內容memcpy到事先mmap好的顯存地址空間。

  關于 雙緩沖 技術我就不多說了,這技術的解釋已經爛大街了,諸如什么流水線相關的形而上解釋,看著都煩了,不過確實是那么回事。

  直接上代碼吧,先看Java代碼 Drawimage.java:

  import java.awt.image.*;

  import java.io.*;

  import javax.imageio.ImageIO;

  public class Drawimage {

  static File src = null;

  static BufferedImage img = null;

  native static void setFB(int x, int y, int rgb);

  native static void show(int x);

  static {

  System.loadLibrary("setFB");

  }

  static void setPoint(int width, int height, int xoffset, int yoffset) {

  int i, j, rgb, a1;

  for (i = 1; i < width - 1; i++) {

  for (j = 1; j < height-1; j++) {

  rgb = img.getRGB(i, j);

  a1 = (rgb>>24)&0xFF;

  if (a1 != 0) {

  Drawimage.setFB(i + xoffset, j + yoffset, rgb);

  }

  }

  }

  }

  public static void main(String[] args) throws IOException {

  int i, j, width, height, xoffset = 0, yoffset = 0;

  src = new File(args[0]);

  img = ImageIO.read(src);

  width = img.getWidth();

  height = img.getHeight();

  while(true) {

  setPoint(width, height, xoffset%200, yoffset%50);

  Drawimage.show(0); // 清空之前的圖形

  Drawimage.show(1); // 顯示當下的圖形

  try {鄭州不孕不育醫院:http://www.zzfkyy120.com/

  Thread.sleep(100); // 這個時間頻率最好和你的顯示器刷新頻率切合。

  } catch (InterruptedException e) { }

  xoffset += 2; // x漂移

  yoffset += 2; // y漂移

  }

  }

  }

  再看本地代碼 setFB.c :

  #include

  #include

  #include

  #include

  #include

  unsigned int *mem = NULL;

  // 定義第二緩沖區

  unsigned int *back_buffer = NULL;

  static struct fb_var_screeninfo info;

  void setPixel(int x, int y, int c)

  {

  int idx;

  if (x < 0 || x >= info.xres || y < 0 || y >= info.yres) {

  return;

  }

  idx = y*info.xres + x;

  // 操作第二緩沖區,而不是直接操作顯存

  back_buffer[idx] = c;

  }

  JNIEXPORT void JNICALL Java_Drawimage_show (JNIEnv *env, jclass class, int a)

  {

  // show指令下達,說明畫圖操作已經完成,這里一次性替換顯存的內容

  // 注意,替換的時機最好是顯示器刷新的時機,完美契合!!

  if (a) {

  memcpy(mem, back_buffer, info.xres*info.yres*info.bits_per_pixel/8);

  memset(back_buffer, 0, info.xres*info.yres*info.bits_per_pixel/8);

  } else {

  memset(mem, 0, info.xres*info.yres*info.bits_per_pixel/8);

  }

  }

  JNIEXPORT void JNICALL Java_Drawimage_setFB (JNIEnv *env, jclass class, jint x, jint y, int rgb)

  {

  static int fd = -1;

  if (fd == -1) {

  fd = open("/dev/fb0", O_RDWR);

  if (ioctl(fd, FBIOGET_VSCREENINFO, &info)) {

  exit(1);

  }

  info.bits_per_pixel = 8;

  info.xres = 800;

  info.yres = 600;

  if (ioctl(fd, FBIOPUT_VSCREENINFO, &info)) {

  exit(1);

  }

  mem = (unsigned int *)mmap(NULL, info.xres*info.yres*info.bits_per_pixel/8, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

  if (mem == NULL) {

  printf("exit\n");

  exit(1);

  }

  back_buffer = (unsigned int *)mmap(NULL, info.xres*info.yres*info.bits_per_pixel/8, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  if (back_buffer == NULL) {

  printf("back_buffer exit\n");

  exit(1);

  }

  }

  setPixel(x, y, rgb);

  }

  動圖不閃哦:

  雙緩沖的原理就是這么簡單。10年前看的的那些冗長的Java代碼,都是假的,及其虛假。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

礼泉县| 务川| 福建省| 台南市| 加查县| 名山县| 攀枝花市| 上蔡县| 中方县| 且末县| 五指山市| 台湾省| 浙江省| 临桂县| 双柏县| 大化| 保德县| 上栗县| 宝丰县| 泌阳县| 桂阳县| 诸城市| 韩城市| 玛沁县| 永胜县| 连平县| 连江县| 特克斯县| 永昌县| 仁怀市| 东港市| 商南县| 来宾市| 东阳市| 尼勒克县| 阳新县| 柳林县| 黄平县| 嘉善县| 从江县| 高清|