OpenGl Displays 2D Images

Keywords: Qt less

  • Understanding Opengl

Opengl is more efficient in displaying 2D images than using interfaces on the platform, because less CPU runtime is used.

It's not long to learn Opengl, just know the method of pipeline, Shade's method has time to learn; Opengl has many versions, using Qt to respond to Opengl modules, but it's different from the common Win32 program. There are two window classes in Qt to support Opengl, QGL Widget and QOpengl. Widgets, which are older versions and newer classes, don't make much difference.

void initializeGL(); for initialization,
void paintGL(); used to draw various primitives and texture maps

  • Texture Mapping Method

Code to initialize texture size:

unsigned char* image_data = nullptr;
	int pixel_count = CImageW * CImageH;
	DATA_SIZE = pixel_count * 4;
	DATA_SIZE3 = pixel_count * 3;
	image_data = (unsigned char*)malloc(sizeof(unsigned char) * DATA_SIZE);
	for (int i = 0; i < pixel_count; i++) {
		image_data[i * 4 + 0] = 255;
		image_data[i * 4 + 1] = 255;
		image_data[i * 4 + 2] = 255;
		image_data[i * 4 + 3] = 255;
	}
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	
	/* Setting Texture Options */
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, CImageW, CImageH, 0, GL_BGRA, GL_UNSIGNED_BYTE, image_data);
	free(image_data);
	

If texture mapping is done by switching buffers, two ping-pong buffers need to be further bound. http://www.songho.ca/opengl/gl_pbo.html

glGenBuffersARB(2, pboIds);
	glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[0]);
	glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE3, 0, GL_STREAM_DRAW);
	glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[1]);
	glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE3, 0, GL_STREAM_DRAW);
	glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0);

In fact, there is no official improvement in testing, although the glTexImage 2D function is almost time-consuming, and the efficiency of binding caching is not very high.

In addition, there are some laptop graphics cards that do not seem to support this method, that is, the call of glTex Image 2D function is still time-consuming.

Display function code:

If it's a simple direct display

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)HwManager.getImageWidth(), (GLsizei)HwManager.getImageHeight(), GL_BGR, GL_UNSIGNED_BYTE, pGLBuffer);
GLenum result = glGetError();
qDebug() << "GLenum:" << result;
GLdouble viewMatrix[16];
glGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
GLdouble projectionMatrix[16];
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
GLint    viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);


glBindTexture(GL_TEXTURE_2D, texture);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[index]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)HwManager.getImageWidth(), (GLsizei)HwManager.getImageHeight(), GL_BGR, GL_UNSIGNED_BYTE, 0);
// start to modify pixel values ///////////////////
// bind PBO to update pixel values
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pboIds[nextIndex]);
// map the buffer object into client's memory
// Note that glMapBuffer() causes sync issue.
// If GPU is working with this buffer, glMapBuffer() will wait(stall)
// for GPU to finish its job. To avoid waiting (stall), you can call
// first glBufferData() with NULL pointer before glMapBuffer().
// If you do that, the previous data in PBO will be discarded and
// glMapBuffer() returns a new allocated pointer immediately
// even if GPU is still working with the previous data.
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE3, 0, GL_STREAM_DRAW);
ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
if (ptr)
{
	//
	if (pGLBuffer != NULL)
	{
		mutex.lock();
		memcpy(ptr, pGLBuffer, DATA_SIZE3);
		//ptr = pGLBuffer;
		mutex.unlock();
	}
	glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER);  // release pointer to mapping buffer
}
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER);  // release pointer to mapping buffer
// measure the time modifying the mapped buffer
// it is good idea to release PBOs with ID 0 after use.
// Once bound with 0, all pixel operations behave normal ways.
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0);

 

Posted by x2fusion on Thu, 29 Aug 2019 01:55:49 -0700