如何在最低级别绘制像素

时间:2014-01-01 15:10:37

标签: c++ assembly gdi

我可以使用setpixel(GDI)设置屏幕上的任何像素颜色。

那么我将如何在最低的装配级别重现Setpixel。实际上发生了什么触发了指令,即在帧缓冲区中将一个字节放在x位置。

4 个答案:

答案 0 :(得分:1)

setpixel最有可能只是使用公式计算给定像素的地址:

pixel =(frame_start + y * frame_width)+ x

然后它只是* pixel = COLOR

您实际上可以使用CreateDIBSection创建自己的缓冲区并将其与DeviceContext关联,然后您可以使用上面的公式修改低级别的像素。如果您拥有自己的图形库,如AGG,这将非常有用。

了解GDI我想查看WINE源代码,在这里你可以看到它实际上有多复杂(dibdrv_SetPixel):

http://fossies.org/dox/wine-1.6.1/gdi32_2dibdrv_2graphics_8c_source.html

它还必须考虑剪裁区域,以及不同的像素大小和可能的其他功能。也有可能某些驱动程序可能以某种方式加速硬件,但我还没有听说过它。

答案 1 :(得分:1)

如果要重新创建setpixel,则需要了解图形硬件的工作原理。大多数硬件制造商至少遵循VESA标准,参见here。该标准规定您可以使用中断0x10设置显示模式。

设置显示模式后,显示的内存区域在标准中定义,您只需直接写入显示内存即可。

高级图形硬件与标准不同(因为它仅涵盖基础知识)。因此,上述功能不适用于高级功能。你将不得不求助于gpu文档。

答案 2 :(得分:0)

“how”总是取决于“what”,我的意思是对于不同的设置有不同的方法,不同的系统有不同的方法,常见的是它们通常不允许你直接这样做,即写到将要显示的内存地址。

某些具有专用设置的设备可能允许您这样做(就像我知道的一些控制台那样)但是你必须做一些锁定或其他实用程序工作才能使其正常工作。

因为在现代PC中,图形加速器被融合到视频卡中(一个例子是Voodoo 1,它需要一个视频卡才能运行,因为它只是一个3D加速器)GPU通常会保留内存。从帧缓冲区中抽取它自己的记忆,使其无法从外部进入。

所以一般来说,你会说这是一个内存地址,将数据“下载”到你自己的GPU内存中并在屏幕上显示,这就是桌面组合的用武之地。由于视频卡一直受到这种转移的影响事实上,发送绘制所需的数据并让GPU进行绘制更快。所以Aero只是一个视觉效果,但据我所知,桌面合成器的工作原理与Aero无关,使绘图GPU依赖。

所以技术上低级别的功能,例如SetPixel,因为我上面提到的东西因为你不能直接访问内存所以是Windows7以来的软件。所以我认为它可能会对每个HDC都有一个位图,当您使用设置像素时,您只需在该位图中设置一个像素,稍后将其发送到GPU进行显示。

如果是DOS或其他旧技术。它可能只是一种仿真,就像对GDI一样。

因此,根据这些,

  

那么如何在最低的装配级别重现Setpixel。

它可能只是一个内存位置的副本,但是窗口集成了窗口表面和它的frambuffer,你将无法直接访问它。模拟它的作用的一种方法是使位图获取内存指针并手动设置像素,然后告诉windows在屏幕上显示此位图。

  

触发指令的实际情况是,在帧缓冲区中确定一个字节x位置。

就像我之前所说的那样,它实际上取决于环境在你进行此调用时所做的事情,而需要执行的代码来自不同的地方,有些是由Microsoft完成的,有些是由GPU制造商完成的,这些都会产生你在屏幕上看到的像素的结果。

答案 3 :(得分:0)

为了使用32位颜色的视频模式将像素设置到帧缓冲区,我们需要像素的地址和像素的颜色。 通过地址和颜色,我们可以简单地使用移动指令将颜色设置为帧缓冲
使用EDI-Register作为32位地址寄存器(默认段寄存器为DS)的示例,用于通过移动指令寻址帧缓冲。
x86 intel语法:

 mov edi, Framebuffer   ; load the address(upper left corner) into the EDI-Register
 mov DWORD [edi], Color ; write the color to the address of DS:EDI

第一条指令将EDI-Register加载到帧缓冲区的地址,第二条指令将颜色写入帧缓冲区。

提示计算frambuffer内部像素的地址: 有些Videomodes可能使用较长的扫描线,水平分辨率为更多字节,部分位于可见视图之外。

德克