- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将 JCEF 提供的图像数据作为 ByteBuffer 复制到 OpenGL 纹理。当我使用适当的参数将提供的 ByteBuffer 传递给 glTexSubImage2D() 调用时,应用程序因 EXCEPTION_ACCESS_VIOLATION (0xc0000005) 崩溃。
我正在尝试做的事情:
JCEF 是 CEF(Chromium 嵌入式框架)的 Java 包装器,我目前正在使用离屏渲染模型(因为我想使用 opengl 在 3D 游戏中渲染浏览器)。
JCEF 通过 onPaint 方法从浏览器提供更新的屏幕数据,该方法包含脏矩形列表和包含更新的屏幕数据的 ByteBuffer。
我想使用 glTexSubImage2D 或类似工具将该 ByteBuffer 复制到 OpenGL 纹理上。
我已经确认传递给函数调用的所有值都是有效的,并且 JCEF 提供给我的缓冲区足够长。每次 OpenGL 库调用后调用 glGetError() 都会导致崩溃返回 0。
我的 opengl 库来自 LightWeight Java Game Library 3 (LWJGL3),我在所有其他代码中都使用了它。
在这里和其他各种论坛上对其他线程和问题的搜索都指出传递给 OpenGL glTexSubImage2D() 的 ByteBuffer 太短。我对此进行了两次和三次检查,但情况并非如此。 (据我对 OpenGL 的理解及其对数据格式和类型的解释告诉我。)
首先是一些基础类(class)。该代码是渲染引擎的一部分,因此我只会包含我认为相关的内容,但如果需要,我很乐意附加更多内容。
第一个类是 PreloadedTexture 类。这表示纹理不是直接来自文件,而是以某种方式修改或生成的。它是我的 OpenGL Texture2D 包装器。
package com.base.shader;
import java.nio.ByteBuffer;
import static org.lwjgl.opengl.GL45.*;
public class PreloadedTexture {
int width;//The width of the texture in pixels
int height;//The height of the texture in pixels
int handle;//The OpenGL handle for the texture. This is used to reference this texture in other OpenGL calls
/*
This constructor creates a blank texture with the dimensions specified.
*/
public PreloadedTexture(int width, int height) {
super(Math.random() + "");
this.width = width;
this.height = height;
this.handle = glGenTextures();
glBindTexture(GL_TEXTURE_2D, handle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
/*EDIT: This method was renamed and had the internals changed to not bind the texture to a uniform sampler as mentioned in my comment below. It now just does a call to glBindTexture() as the uniform binding would occasionally return errors.
*/
public void bind(){
glBindTexture(GL_TEXTURE_2D, handle);
}
}
BrowserWindow 类是大部分操作发生的地方,但我已经删除了与此问题无关的所有内容。
package com.base.game;
import com.base.shader.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.awt.*;
import java.util.concurrent.LinkedTransferQueue;
import static org.lwjgl.opengl.GL46.*;
public class BrowserWindow {
private PreloadedTexture texture;//The texture that should be copied to.
private ByteBuffer imgData;//The BytBuffer provided by CEF with the updated screen data.
private LinkedTransferQueue<Rectangle> dirtyRects = new LinkedTransferQueue<>();//The list of dirty rects. The reasoning behind a LinkedTransferQueue is explained below.
int width;//The width of the browser view in pixels.
int height;//The height of the browser view in pixels.
/*
* Creates a browser window with the specified width and height. Initialises a ByteBuffer with image data to draw and a texture to draw to.
*/
public BrowserWindow(int _w, int _h){
width = _w;
height = _h;
imgData = ByteBuffer.allocate(width * height * 4 * Integer.BYTES);//This is later filled by the JCEF code but I have removed that as I know it works.
//The ByteBuffer is filled with bytes representing the screen data in BGRA format. Each Byte is a separate component of a pixel. The pixels are grouped together.
//This results in a structure like so: [B,G,R,A,B,G,R,A,etc.] I have maually checked that this data looks valid by going through portions of it and seeing understandable variances in the values.
texture = new PreloadedTexture(width, height); // An instance of the above PreloadedTexture class. The final destination for the imgData above.
}
//Called when the engine whats to render a frame. This should update the texture of the browser and then render the mesh with this texture. The actual mesh rendering code is ommited because again I know that works and it is not where the issue lies.
public void render(ShaderProgram shaderProgram, Camera camera) {
synchronized (imgData) {
//This block is to allow communication with the CEF thread.
//CEF runs the browser in a seperate thread and the onPaint method is called from there.
//OpenGL is not initialised in that thread however so I have used a LinkedTransferQueue<Rectangle> to transfer the dirty portions that need to be redrawn and the updated ByteBuffer is transferred byt directly setting it on the class.
//Again the actual code that does this has been ommitted as I know by checking the values manually that the data that is transfered is correct.
if (dirtyRects.size() > 0) {
//This just checks that there are dirty portions to update otherwise the call would waste both CPU and GPU time.
ArrayList<Rectangle> rects = new ArrayList<>();
//This provides a list to drop the Rectangles into for ease of access. These rectangles aren;t used at the moment but their implementation can be seen in the below commented out code.
dirtyRects.drainTo(rects);
imgData.rewind();
//This ensures that the imgData buffer is at the beggining.
texture.bind();
//Here I bind the texture to GL_TEXTURE_2D. The actual implementation is shown above in PreloadedTexture class.
System.out.println("Pre Render Error: " + glGetError());
//This checks to see if OpenGL was in an invalid state before and also clears the error buffer to ensure any errors reported from now on actually occur in this method.
System.out.println(glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) + ", " + glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT));
//This is a sanity check to ensure that the texture was initialised correctly in the PreloadedTexture constructor.
System.out.println(imgData.limit() + ", " + width * height * 4);
//This is another sanity check to ensure that the ByteBuffer is actually large enough. At the moment I have given it extra data to work with to see if it was the problem, hence the much larger limit of the ByteBuffer compared to the computed nescesary amount.
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
//These two calls reset the OpenGL state to ensure that rows and pixels aren't being skipped.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imgData);//This line results in the EXCEPTION_ACCESS_VIOLATION (0xc0000005)
System.out.println("Render Error: " + glGetError()); //This is a sanity check from before with another problem that I fixed.
//Below is the implementation that made use of the rectangles. It follows a similar pattern to the above code but only updates the specified rectangles.
// for (Rectangle rect : rects) {
// System.out.println(rect.x + ", " + rect.y + ", " + rect.width + ", " + rect.height);
// glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
// glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
// glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,imgData);
// }
}
imgData.notifyAll();//This notifies the CEF thread that the Rectangles and imgData objects are now free.
}
//Mesh rendering would happen here but again it has been omitted for conciseness this is not where the problem lies.
}
}
正如我在代码注释中提到的,我已仔细检查 CEF 中的数据是否采用有效格式。它遵循 4 字节重复 BGRA 值序列。 ByteBuffer 足够长,如调用 glTexSubImage2D() 之前的健全性检查所示;
抱歉代码量太大,但正如我之前所说,它是渲染引擎的一部分,并且大部分结构都受到这一事实的影响。
我希望调用 glTexSubImage2D() 将 ByteBuffer 数据复制到 OpenGL Texture2D 上,但是调用会导致 EXCEPTION_ACCESS_VIOLATION (0xc0000005)。 ByteBuffer 足够长,并且里面的数据格式有效。我还尝试将 GL_UNSIGNED_INT_8_8_8_8_REV 与 GL_UNSIGNED_INT_8_8_8_8 和 GL_UNSIGNED_BYTE 交换,但它们不会影响结果。查看日志时出现异常,因为它尝试访问地址 0x0000000000000010。
有谁知道什么可能导致此错误。我所有的研究都表明 ByteBuffer 太短了,但是,正如我所说的,我已经仔细检查了这一点。我对正在发生的事情的理解是否有缺陷或者是别的什么?
最佳答案
在查看错误日志并查看库源代码之后,我追踪到错误是如何分配 ByteBuffer 的。 OpenGL 库使用了内存偏移访问器(原因很明显),但获取偏移量的方法要求 ByteBuffer 是直接的。将 BrowserWindow 类更改为使用直接缓冲区已修复该错误。
下面列出了更新的部分,供遇到类似问题的其他人使用。
//This is the updated constructor from the BrowserWindow class
public BrowserWindow(int _w, int _h){
width = _w;
height = _h;
//imgData = ByteBuffer.allocate(width * height * 4 * Integer.BYTES); This is the old line that created a non-direct ByteBuffer.
imgData = ByteBuffer.allocateDirect(width * height * 4);//This is the new line. Note the allocateDirect() call and the removal of the extra space in the buffer in the form of Integer.BYTES.
texture = new PreloadedTexture(width, height);
}
关于java - 尽管确认传递的数据缓冲区足够长,但 glTexSubImage2D() 导致 EXCEPTION_ACCESS_VIOLATION (0xc0000005),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56872469/
TCP header 上的 32 位确认字段,比如 x告诉另一台主机“我收到了所有字节,直到并包括 x-1,现在期待来自 x 和 on 的字节”。在这种情况下,接收方可能已经收到了一些更多字节,比如
我正在使用 PyCharm 2020.2.3 不知不觉中我点击了下图中的复选框 现在,即使我的代码正在调试中,点击运行也会终止调试并开始运行代码。如何将其恢复为未选中状态?谢谢。 PS:我的“允许并行
我想知道何时使用 RabbitMQ 和 Spring Boot 接受 (ack) 或不接受 (nack) 消息。 我想将消息发送到队列(通过交换)并检查队列是否已接受该消息。实际上我想发送到两个不同的
我一直在寻找一种方法让用户确认 票在分配给他们之后。不知道有没有 这是一个内置功能,或者如果有一个插件 将为用户创建一个状态/按钮以接受票证 在它被放入队列之后。我希望 从附近的售票窗口看到类似的东西
我正在构建一个应用程序以通过 Xbee API 与 Xbee 模块通信。 目前我有一些工作,但它相当简单并且有很多限制。 Sub processPackets() ' this runs as its
我有一个复选框,更改后会自动发布。 自动发布对于两者(选中和未选中)都适用,但我想在每个事件发生之前弹出一个对话框进行确认。 到目前为止,当选中该复选框时,弹出框就会起作用。 但当取消选中该复选框时,
当我使用 UIGestureRecognizer ,例如,当用户向右滑动时,我想要一个 UIAlertView询问他是否真的要进行向右滑动的 Action 。 我曾尝试这样做,但没有成功。 最佳答案
我有一个 asp:CheckBoxList,我想显示一条警告消息仅在使用 jquery 取消选中复选框时。 $('.chklist').click( function () {
我想知道有什么可能的方法来确定我们的推送消息是否最终从 APNS 服务器传送。我已经想出了一些信息,如下所述 APNS 正在发送接受推送请求的响应代码,并可能给出错误代码(如果有)。例如:如果您的有效
我有此页面,我正在尝试确认输入文本字段中的日期与当前日期。如果输入字段中的日期晚于当前日期,则需要出现确认框以确认他们输入了正确的日期。因此,“确定”按钮需要完成数据提交,“取消”按钮需要将它们返回到
我有一个功能: function placeOrder(price, productList) { var bulletinBoardItem = Number(productList.box
我不明白为什么即使我点击“否”,这个confirm()调用也会被触发。你能告诉我我做错了什么吗? $('.deleteButton').livequery('click',function(){
我目前正在使用 dotmailer 生成一个新表单(简单的文本框和提交按钮),自动将电子邮件地址添加到 dotmailer 地址簿。 当有人提交电子邮件地址时 - 他们可以被带到网页。 我一直在尝试
这是不起作用的代码...它只是删除表单而不先提示。 $(".delete").click(function () { if(confirm('You honestly want to dele
我在我的程序中使用 aprgeparse 创建一个参数,允许用户从 amazon s3 存储桶中删除文件。我以这种方式创建它: parser.add_argument("-r", "--remove"
我正在努力学习 puppeteer 操作。我已经成功编写了登录页面和一些导航的脚本。然后我让它点击一个按钮。该页面抛出一个 window.confirm,我希望我的脚本接受它以继续下一步,但我不知
某网站实现了一个第三方插件,提示用户在删除前进行确认。 confirmDelete: function (event) { var go_ahead = confirm("Are you su
我想在 primefaces 的选择/取消选择复选框上显示确认对话框。我试过了 但它不起作用,因为 selectBooleanCheckBox 不可确认。是否有解决此问题的解决方法? 最
我们已经从 TFS 下载了一个项目,在恢复 Nuget 包后,我们收到以下错误: Error 5 The "ValidatePackageReferences" task could not
我有两个单独的 ul 列表:列表 A 和列表 B 由于 jQuery UI 插件,它们都可以排序。 我正在开发的项目的用户希望在项目从一个列表移动到另一个列表时确认操作,但在同一列表内移动时则不需要。
我是一名优秀的程序员,十分优秀!