Hello,
I'm using the imx8mp development board, with a simple MIPI camera module plugged on the CSI interface. It works fine and streams the video as expected using gstreamer and v4l2src.
I've been trying to of glTexDirectVIVMap as described in i.MX_Graphics_User's_Guide.pdf in on of my own programs, which simply opens the ISI camera interface (say /dev/video3), configures it, gets 4 buffers via ioctl VIDIOC_QUERYBUF, then mmap them like so :
void *data = mmap(
NULL,
buffer.m.planes[0].length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
_cameraFD,
buffer.m.planes[0].m.mem_offset
);
The buffers are then queued with VIDIOC_QBUF, then in the thread that handles the reception of frames, dequeued when ready and set aside for the rendering thread which make use of glTexDirectVIVMap so that said buffer is mapped to a given openGL texture ID.
I call "glTexDirectInvalidateVIV" right after glTexDirectVIVMap so that the reference gets updated on the GL side (if I understood correctly what it does).
Rendering is then done, and when another ready frame has been set aside, we call glTexDirectVIVMap, glTexDirectInvalidateVIV, and release the previous one, that gets requeued for v4l2.
void CameraPreview::updateTexture()
{
static GLvoid **buffer = (GLvoid **)aligned_alloc(64, 8 * (sizeof(GLvoid *))); // Buffer and pointers needs to be 64 bits aligned
memset(buffer,0, 8 * sizeof(GLvoid *));
buffer[0] = _camDevice.getBuffer();
if (buffer[0])
{
uint32_t physicalBufferAddress = _camDevice.getPhysicalBufferAddress();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _camTextureID);
// =============UGLY BUT NOTHING BETTER AS IT CRASH IF USING THE ISI BUFFER DIRECTLY...
// static void *thisIsUgly = aligned_alloc(64, 1280*1024*2);
// memcpy(thisIsUgly, buffer[0], 1280*1024*2);
// physicalBufferAddress = ~0U;
//======================================================================
glTexDirectVIVMap(GL_TEXTURE_2D, _camResW, _camResH, GL_VIV_YUY2, (GLvoid **)buffer, &physicalBufferAddress);
//glTexDirectVIVMap(GL_TEXTURE_2D, _camResW, _camResH, GL_VIV_YUY2, (GLvoid **)&thisIsUgly, &physicalBufferAddress);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexDirectInvalidateVIV(GL_TEXTURE_2D);
if (_camDevice.getHeldBuffersCount() > 1)
{
_camDevice.releaseBuffer(); // If we're tied to a previous buffer, liberate it
}
}
}
Probably not the best code, it's just a test / example.
It crashes the kernel with a "AXI BUS ERROR", despite the buffer supposedly not being used elsewhere. I've dequeued it from V4L2, mapped it to the GL Texture for direct access by the GPU, and that's all.
[15256.493410] AXI BUS ERROR
[15256.596880] **************************
[15256.600650] *** GPU DRV CONFIG ***
[15256.604415] **************************
[15256.608185] Galcore version 6.4.3.398061
[15256.612131] Galcore options:
[15256.615019] irqLine = 83
[15256.618612] registerMemBase = 0x38000000
[15256.622892] registerMemSize = 0x00008000
[15256.627178] irqLine2D = 84
[15256.630760] registerMemBase2D = 0x38008000
[15256.635040] registerMemSize2D = 0x00008000
[15256.639318] contiguousSize = 0x10000000
[15256.643596] contiguousBase = 0x0
[15256.647257] externalSize = 0x00000000
[15256.651535] externalBase = 0x0
[15256.655195] bankSize = 0x00000000
[15256.659475] fastClear = -1
[15256.663048] compression = 15
[15256.666631] powerManagement = 1
[15256.670134] baseAddress = 0x40000000
[15256.674417] physSize = 0xC0000000
[15256.678694] recovery = 0
[15256.682189] stuckDump = 0
[15256.685683] userClusterMask = 0x0
[15256.689399] GPU smallBatch = 1
[15256.692992] allMapInOne = 1
[15256.696538] mmuException = 1
[15256.700046] irqs =
[15256.700050] 83,
[15256.703459] 85,
[15256.705295] -1,
[15256.707132] -1,
[15256.708982] -1,
[15256.710821] -1,
[15256.712673] -1,
[15256.714510] -1,
[15256.716359] 84,
[15256.718197] -1,
[15256.723371] registerBases =
[15256.723390] 0x38000000,
[15256.726797] 0x38500000,
[15256.729343] 0x00000000,
[...]
If you look at the source code I pasted earlier, there's commented lines that creates a dummy buffer (aligned on 64bit), in which I copy the content of the buffer I got from v4l2, then I map it to the texture with glTexDirectVIVMap and it works flawlessly. I want to avoid making an unecessary memcpy of a whole frame each time I get a new one of course...
So I'm a bit puzzled. It looks like all the exemples and sources using glTexDirectVIVMap I could find, and obviously something is wrong. Does anyone had the same, or a similar issue and could shed a light on what's going on ?
Thanks !
Solved! Go to Solution.
Hello KailoKyra,
The address from V4L2_MEMORY_MMAP is virtual address, glTexDirectVIVMap need is physical address, you can use V4L2_MEMORY_USERPTR + g2d_alloc to get buffer with physical address, and then there should be no problem with glTexDirectVIVMap.
Regards
Hello KailoKyra,
The address from V4L2_MEMORY_MMAP is virtual address, glTexDirectVIVMap need is physical address, you can use V4L2_MEMORY_USERPTR + g2d_alloc to get buffer with physical address, and then there should be no problem with glTexDirectVIVMap.
Regards
Thanks for your reply, that led me to realize that glTexDirectVIVMap needs the PHYSICAL (really as in "physical address", not kernel space or whatnot (yes, after all it's in the name !).
The "buffer.m.planes[0].m.mem_offset" field obtained with VIDIOC_QBUF is not a physical address (and that was what I was using).
So I ended up doing that as the documentation indicates that you can just use a pointer set with (GLuint *)~0U... address if you don't have any physical address:
const Gluint *physicalBufferAddress = (GLuint *)~0U;
glTexDirectVIVMap(GL_TEXTURE_2D, _camResW, _camResH, GL_VIV_YUY2, (GLvoid **)buffer, physicalBufferAddress);
glTexDirectInvalidateVIV(GL_TEXTURE_2D);
And it automagically worked with the V4L2_MEMORY_MMAP interface :). No need to bother with V4L2_MEMORY_USERPTR + g2d_alloc. (Or maybe there's a hidden benefit that I don't see ?)
Thanks a lot for your help !