搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
Gausst松鼠会
这个屌丝很懒,什么也没留下!
关注作者
热门标签
article
热门文章
1
人工神经网络原理及应用,神经网络的数学原理_人工神经网络走神是同步吗
2
SpringBoot环境下JPA的使用_jpa springboot
3
K8S动态PV
4
【C/C++ 01】初级排序算法
5
hsv量化后用颜色直方图进行图像相似度比对_为什么求直方图对比要变换到hsv空间
6
TestFlight 提交提示“处理你的请求时出错。请稍后再试“下载提示“所请求的app不可以或者不存在“,报错422_testflight怎么发布处理你的请求时出错。请稍后再试。
7
docker + docker-compose 配置安装、基础教程(Ubuntu 18.04 LTS)_docker-ce-18.04 装compos
8
以太坊智能合约项目开发——Web3.py库安装及错误解决方案
9
stm32f4 mpu6050与姿态解算(仅供自己学习使用,学习笔记)_mpu6050姿态解算
10
vue sm2加密解密_vue使用sm2加解密
当前位置:
article
> 正文
双缓冲(Double Buffer)原理和使用_pwm double buffer
作者:Gausst松鼠会 | 2024-02-11 15:58:04
赞
踩
pwm double buffer
原文转自:http://blog.csdn.net/xiaohui_hubei/article/details/16319249
一、双缓冲作用
双缓冲甚至是多缓冲,在许多情况下都很有用。一般需要使用双缓冲区的地方都是由于“生产者”和“消费者”供需不一致所造成的。这样的情况在很多地方后可能会发生,使用多缓冲可以很好的解决。我举几个常见的例子:
例 1. 在网络传输过程中数据的接收,有时可能数据来的太快来不及接收导致数据丢失。这是由于“发送者”和“接收者”速度不一致所致,在他们之间安排一个或多个缓冲区来存放来不及接收的数据,让速度较慢的“接收者”可以慢慢地取完数据不至于丢失。
例2. 再如,计算机中的三级缓存结构:外存(硬盘)、内存、高速缓存(介于CPU和内存之间,可能由多级)。从左到右他们的存储容量不断减小,但速度不断提升,当然价格也是越来越贵。作为“生产者”的 CPU 处理速度很快,而内存存取速度相对CPU较慢,如果直接在内存中存取数据,他们的速度不一致会导致 CPU 能力下降。因此在他们之间又增加的高速缓存来作为缓冲区平衡二者速度上的差异。
例3. 在图形图像显示过程中,计算机从显示缓冲区取数据然后显示,很多图形的操作都很复杂需要大量的计算,很难访问一次显示缓冲区就能写入待显示的完整图形数据,通常需要多次访问显示缓冲区,每次访问时写入最新计算的图形数据。而这样造成的后果是一个需要复杂计算的图形,你看到的效果可能是一部分一部分地显示出来的,造成很大的闪烁不连贯。而使用双缓冲,可以使你先将计算的中间结果存放在另一个缓冲区中,但全部的计算结束,该缓冲区已经存储了完整的图形之后,再将该缓冲区的图形数据一次性复制到显示缓冲区。
例1 中使用双缓冲是为了防止数据丢失,例2 中使用双缓冲是为了提高 CPU 的处理效率,而例3使用双缓冲是为了防止显示图形时的闪烁延迟等不良体验。
二、双缓冲原理
这里,主要以双缓冲在图形图像显示中的应用做说明。
上面例3中提到了双缓冲的主要原理,这里通过一个图再次理解一下:
图 1 双缓冲示意图
注意,显示缓冲区是和显示器一起的,显示器只负责从显示缓冲区取数据显示。我们通常所说的在显示器上画一条直线,其实就是往该显示缓冲区中写入数据。显示器通过不断的刷新(从显示缓冲区取数据),从而使显示缓冲区中数据的改变及时的反映到显示器上。
这也是显示复杂图形时造成延迟的原因,比如你现在要显示从屏幕中心向外发射的一簇射线,你开始编写代码用一个循环从0度开始到360度,每隔一定角度画一条从圆心开始向外的直线。你每次画线其实是往显示缓冲区写入数据,如果你还没有画完,显示器就从显示缓冲区取数据显示图形,此时你看到的是一个不完整的图形,然后你继续画线,等到显示器再次取显示缓冲区数据显示时,图形比上次完整了一些,依次下去直到显示完整的图形。你看到图形不是一次性完整地显示出来,而是每次显示一部分,从而造成闪烁。
原理懂了,看下 demo 就知道怎么用了。下面先介绍 Win32 API 和 C# 中如何使用双缓冲,其他环境下由于没有用到所以没写,等用到了再在下面补充,不过其他环境下过程也基本相似。
三、双缓冲使用 (Win32 版本)
[cpp]
view plain
copy
LRESULT
CALLBACK WndProc(
HWND
hWnd,
UINT
message,
WPARAM
wParam,
LPARAM
lParam)
{
HDC
hDC, hDCMem;
HBITMAP
hBmpMem, hPreBmp;
switch
(message)
{
case
WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
/* 创建双缓冲区 */
// 创建与当前DC兼容的内存DC
hDCMem = CreateCompatibleDC(hDC);
// 创建一块指定大小的位图
hBmpMem = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
// 将该位图选入到内存DC中,默认是全黑色的
hPreBmp = SelectObject(hDCMem, hBmpMem);
/* 在双缓冲中绘图 */
// 加载背景位图
hBkBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
hBrush = CreatePatternBrush(hBkBmp);
GetClientRect(hWnd, &rect);
FillRect(hDCMem, &rect, hBrush);
DeleteObject(hBrush);
/* 将双缓冲区图像复制到显示缓冲区 */
BitBlt(hDC, 0, 0, rect.right, rect.bottom, hDCMem, 0, 0, SRCCOPY);
/* 释放资源 */
SelectObject(hDCMem, hPreBmp);
DeleteObject(hMemBmp);
DeleteDC(hDCMem);
EndPaint(hWnd, &ps);
break
;
}
}
使用 Win32 版本时注意释放资源,释放顺序与创建顺序相反。我在使用过程中不小心遗漏了一句上面的 "DeleteObject(hMemBmp);"导致图形显示一段时间后就卡死了,查看内存使用发现内存随时间推移飙升,加上上面这句代码后,就没这个问题了。这也再次提醒我们释放资源是多么重要,成对编程的习惯是多么重要。
图 2 处理几次
WM_PAINT
消息后内存变化图
在使用过程中,如果想更新使用双缓冲区显示的区域,可以使用 InvalidateRect(hWnd, &rect, FALSE); ,这里要注意第三个参数一定要设置成 FALSE ,第三个参数表示更新第二个参数指定的区域时是否擦除背景,因为使用双缓冲技术时是直接复制整个缓冲区数据到显示缓冲区,因此无论原有缓冲区里面有什么都会被覆盖,因此第三个参数设置成 FALSE 有助于提高新能。更主要的原因是,如果先擦除原有缓冲区,会导致中间有一瞬间显示缓冲区被清空(显示为默认背景色),然后等到复制了双缓冲区的数据后再显示新的图像,这将导致闪烁!这与使用双缓冲的本意相违背,所以要注意这一点。
四、双缓冲使用 (MFC 版本)
[cpp]
view plain
copy
void
CGame2Dlg::OnPaint()
{
CPaintDC dc(
this
);
// device context for painting
CRect rect;
GetClientRect(&rect);
// 创建内存DC
CDC memDC;
memDC.CreateCompatibleDC(&dc);
// 创建内存位图
CBitmap bmp;
bmp.CreateCompatibleBitmap(&memDC, rect.right - rect.left, rect.bottom - rect.top);
// 将位图选入DC
memDC.SelectObject(&bmp);
// 绘图
m_pGameEngine->Show(memDC.m_hDC);
// 将后备缓冲区中的图形拷贝到前端缓冲区
dc.BitBlt(0, 0, rect.right - rect.left, rect.bottom - rect.top, &memDC, 0, 0, SRCCOPY);
}
五、双缓冲使用 (C# 版本)
[csharp]
view plain
copy
public
void
Show(System.Windows.Forms.Control control)
{
Graphics gc = control.CreateGraphics();
// 创建缓冲图形上下文 (类似 Win32 中的CreateCompatibleDC)
BufferedGraphicsContext dc =
new
BufferedGraphicsContext();
// 创建指定大小缓冲区 (类似 Win32 中的 CreateCompatibleBitmap)
BufferedGraphics backBuffer = dc.Allocate(gc,
new
Rectangle(
new
Point(0, 0), control.Size));
gc = backBuffer.Graphics;
// 获取缓冲区画布
/* 像使用一般的 Graphics 一样绘图 */
Pen pen =
new
Pen(Color.Gray);
foreach
(Step s
in
m_steps)
{
gc.DrawLine(pen, s.Start, s.End);
}
// 将双缓冲区中的图形渲染到指定画布上 (类似 Win32 中的)BitBlt
backBuffer.Render(control.CreateGraphics());
}
其他版本后续用到时再补充。
参考资料:
文中用到的 Win32 API 在MSDN中的说明:
CreateCompatibleDC
CreateCompatibleBitmap
BitBlt
C# 中使用double buffer
http://msdn.microsoft.com/en-us/library/ms229622(v=vs.110).aspx
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/blog/article/detail/76006
推荐阅读
article
c++
关于
求
质数
的实现
_
质数
c++
关于
c++
中求
质数
的实现
_
质数
c++
质数
c++
...
[详细]
赞
踩
article
st
m3
2
启动
过程、
cortex
-
m3
架构
、堆栈代码位置、编译汇编链接分析
分析一、寄存器、
架构
、工作流程 1、寄存器
架构
二、总线与各个部件之间的关系(主要是I-CodeBus、D-CodeBus、SystemBus) 体系结构:哈佛结构与冯诺依曼结构的区别 复位有三种
启动
方式,从哪里开始
启动
、
启动
代码的...
[详细]
赞
踩
article
FreeRTOS
内存
He
ap
管理_
ap
use too much ram,
he
ap
less than min_
he
ap
_
size
_
@(嵌入式)FreeRtosFreeRtos提供的几种
he
ap
管理在源码目录Source/Portable/MemMang下,选择哪种类型管理直接在编译时把原文件加入(比如在makefileSRC中加入)即可,堆大小是FreeRTOSCon...
[详细]
赞
踩
article
可拖拽
分隔
面板(
vue
-
splitpane
)
可拖拽
分隔
面板(
vue
-
splitpane
)_
vue
-
splitpane
vue
-
splitpane
使用
vue
-
splitpane
组件可实现垂直或者水平的面板
分隔
1、安装npminstall
vue
-
splitpane
12、引入(在需要引入vu...
[详细]
赞
踩
article
云
计算
技术,主要
包括
哪些
关键技术
?_
云
计算
的
关键技术
包括
云
计算
的
关键技术
包括
虚拟化,分布式存储,分布式
计算
,多租户。物联网中存在
的
大量数据需要与
云
计算
和大数据结合1.虚拟化将一台
计算
机虚拟成多台
计算
机,多个应用程序在相互独立
的
空间运行,显著提高
计算
机工作效率。2.分布式存储集中式存储无法满足海量...
[详细]
赞
踩
article
超
完整
素数
算法
总结归纳
目录
素数
的判定Eratosthenes筛选(
素数
筛选)因子数与因子和完美数n的第k个因子分拆质数和分解质因数最接近的因数丑数
素数
的判定Eratosthenes筛选(
素数
筛选)因子数与因子和完美数n的第k个因子分拆质数和分解质因数四因数最接近...
[详细]
赞
踩
article
解决linux(Ubuntu)
crontab
任务调度
不执行及总结
crontab
基本使用方法._
starting
periodic
command
scheduler
解决
crontab
任务调度
不执行可能的情况:
crontab
的服务没开文件无可执行权限
crontab
写入格式错误,执行路径错误等本文只叙述情况1的解决方案.jill@DESKTOP-EIC0724:~$sudoservicecronstart...
[详细]
赞
踩
article
执行
任务
Ubuntu使用
crontab
定时
任务
查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法正确的,以免误导读者,也是给自己做个记录吧!因为明天想定时
执行
postgres的一些脚本,所以在网上查一下有一个
crontab
的命令,就把这个命令的应用记录一下,便利往后查找.c...
[详细]
赞
踩
article
Python
-
day12
(数据容器【序列】的切片,
集合
的定义与
操作
)_
取出
差集
和
消除
差集
有
区别吗
列表可修改,支持重复元素且
有
序。元组、字符串不可修改、支持重复元素且
有
序。具
有
支持重复元素的局限,去重
操作
就不方便。
集合
,不支持重复元素,且无序。_
取出
差集
和
消除
差集
有
区别吗
取出
差集
和
消除
差集
有
区别吗 数据容器【序列】的切片序列:...
[详细]
赞
踩
article
第二届
全国
大学生
算法设计与编程
挑战赛
D题:
兰德
索尔
杯-
cup
_
第二届
全国
大学生
算法设计与编程
挑战赛
-d-
兰德
索尔
杯-
cup
问题描述:半年一度的
兰德
索尔
杯开幕了!
兰德
索尔
杯是一个趣味跑步比赛。参加比赛的成员四人一组,在不同的赛道上进行跑步。下图就是跑步的一个场景:可以看到,跑道上充满了一些特殊物件:加速阵、障碍物、魔物等等。这使得比赛充满了乐趣(你看她们玩的多开...
[详细]
赞
踩
article
VMWare
-
vSphere
体系架构
https://www.cnblogs.com/snow-wolf/category/1201727.html
VMWare
虚拟化一些知识转载https://www.cnblogs.com/snow-wolf/articles/8880418...
[详细]
赞
踩
article
PyCharm
+
QTDesigner
+
PyUIC
+
PyRCC
使用
教程_
pyrcc
怎么用
PyCharm
+
QTDesigner
+
PyUIC
使用
教程我们在
PyCharm
安装配置QtDesigner+
PyUIC
教程中已配置好了
PyCharm
+
QTDesigner
+
PyUIC
环境这里在此基上我们演示如何
使用
这些工具,编写一个图形界面程...
[详细]
赞
踩
article
python
高性能编程
AOT
VS
JIT
_
python
aot
python
的动态性deff(x,y):returnx+yprint(f(1,2))print(f("a","b"))
python
具有动态性但实际较少用到,这给编译器的编译带来困难,编译时会进行选择跳转,导致动态语言很慢.
AOT
提前编译ah...
[详细]
赞
踩
article
Linux
基础命令、
Linux
简单
服务器
搭建(Web、
DHCP
、
DNS
、
Samba
、NFS、
Sendmail
、Postfix)_
samba
排序方式
Linux
基础命令、
Linux
简单
服务器
搭建(Web、
DHCP
、
DNS
、
Samba
、NFS、
Sendmail
、Postfix)_
samba
排序方式
samba
排序方式1.三个基本命令lspwdcdpwd表示现在命令所处目录ls列出当前目录下所...
[详细]
赞
踩
article
第二届全国大学生算法设计与编程挑战赛B题:
数位
dp
-
dp
_小
x
对
数位
dp
很感兴趣
,
现
在
他
在
解决
一道
题目
,
要求
求解出[
x
,
y
][
x
,
y
]闭区间内所有满
小
x
对
数位
dp
很感兴趣
,
现
在
他
在
解决
一道
题目
,
要求
求解出[
x
,
y
]闭区间内所有满足以下性质的数字个数:相邻位数字差值的绝对值不能超过7。且最低位与最高位差值的绝对值要大于2。
现
在
,给出
x
=13930,
y
=457439。请你告诉小
x
,满足
要求
...
[详细]
赞
踩
article
Codeforces
Round
#698 (Div. 2)
_
codeforces
round
698 (
div
.
1
)
A:NezzarandColorfulBalls 给你一个序列,你可以选择一个严格递增序列划分成一组,问你最少只需要划分几组。典型的贪心问题,划分成一组时尽可能地把能加入的元素都加入当前的序列中。#include
[详细]
赞
踩
article
nohup
java
-
jar
之
nohup
命令
_
java
-
jar
nohup
在应用Unix/Linux时,我们一般想让某个程序在后台运行,于是我们将常会用&在程序结尾来让程序自动运行。而有些则无法使用&来自动运行采用项目中的
nohup
方式存底
nohup
命令
用途:不挂断地运行
命令
。语法:
nohup
Co...
[详细]
赞
踩
article
裸机
PWM
驱动
屏幕
亮度
(
Linux
驱动
开发篇)_
pwm
duty
1、
PWM
简介
PWM
信号有两个关键的术语:频率(开关速度)占空比(t/T)2、
pwm
控制屏幕
亮度
的原理假如我们不断的打开和关闭背光,当速度足够快的时候就不会感觉到背光关闭这个过程了我们给LCD的背光引脚输入一个
PWM
信号,这样就可以通过调整...
[详细]
赞
踩
article
vue
从
入门
到
精通_
vue
入门
到
精通
VUE
vue
框架的两大核心:数据驱动和组件化。第一周:大家需要转变编程思维的习惯:数据驱动(数据的变化会驱动页面发生变化,不用操作DOM)第二周:大家需要转变编程思维的习惯:组件化(封装的是页面)一、前端开发历史1994年可以看做前端历史的...
[详细]
赞
踩
article
windows
运行
jar
包
和开机
自动
启动_
jar
包
自动
运行
脚本
整理了一些在
windows
系统常用的
jar
包
运行
批处理命令执行文件:新建一个.bat文件放置在
jar
包
同目录下,如run.bat,根据需要编辑好以下命令双击
运行
就可以了。
运行
jar
文件(bat文件):@echooffjava-
jar
xxxx...
[详细]
赞
踩
相关标签
c++
c语言
stm32
架构
单片机
heap
内存
内存管理
嵌入式
vue.js
javascript
前端
云技术
散列表
数据结构
leetcode
蓝桥杯
开发工具
python
开发语言
pycharm
学习
windows
运维