New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix uiImage on mac #402
Fix uiImage on mac #402
Conversation
Half of those I've already fixed and I thought I pushed it but I guess I didn't? Will check again later. |
Why is the stride even needed ? Only for future usage ? The macOS code supports only bytePerPixel = 4 because of the data reordering: Lines 48 to 52 in cda991b
and Lines 60 to 61 in cda991b
Linux uses with CAIRO_FORMAT_ARGB32 and calculates it's own stride, so also 4 bytes:Line 45 in cda991b
Windows also uses |
a9068d5
to
463daf4
Compare
All right, I actually pushed the fixes this time. Try again. I know there are some things you said that I didn't cover in those fixes, so I'm not sure which still need to be merged in. Stride is a standard parameter when storing image data in memory, because it's sometimes faster to have extra columns on the right side that are ignored when actually drawing the image, depending on the hardware. |
463daf4
to
da1d870
Compare
I updated the PR. Remaining problems: Running the tester on macOS, I get this when closing the window:
It doesn't happen with this line commented out: Line 25 in cda991b
On Linux, this line Line 46 in cda991b
allocates cstride * pixelHeight * 4 = pixelWidth * 4 * pixelHeight * 4 bytes which seems to be 4 times too many.
|
da1d870
to
fb694ed
Compare
darwin/image.m
Outdated
@@ -40,18 +40,21 @@ void uiImageAppend(uiImage *i, void *pixels, int pixelWidth, int pixelHeight, in | |||
// OS X demands that R and B are in the opposite order from what we expect | |||
// we must swizzle :( | |||
// LONGTERM test on a big-endian system | |||
swizzled = (uint8_t *) uiprivAlloc((pixelStride * pixelHeight * 4) * sizeof (uint8_t), "uint8_t[]"); | |||
swizzled = (uint8_t *) uiprivAlloc((pixelWidth * pixelHeight * 4) * sizeof (uint8_t), "uint8_t[]"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be just (pixelStride * pixelHeight)
.
On linux too, on windows it is already
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Linux, it computes cstride
, which is basically pixelWidth * 4
.
If I understood andlabs correctly, then the input pixels
array can contain unused data at the end of every row. We don't need this data for drawing the image so pixelWidth * 4
should be fine. pixelWidth * 4
is in most cases = pixelStride
, but always pixelWidth * 4 < pixelStride
.
On Windows, pixelStride
is passed to the parameter cbStride
: "The number of bytes between successive scanlines in pbBuffer". So the row size of the input data.
If we want to be cross-platform, But maybe I'm wrong - as this function is not optimized for speed anyway, copying bytes one-by-one is slow - so different input and internal stride is ok. For realtime there should be different function - returning pointer to internal framebuffer, on what game engine will draw directly. |
It is (the
From #2 (comment):
So this is really an |
I've already forgotten what the precise definition of stride is in libui. I'll have to go back and fix that, since it's part of the documentation. |
The ASAN crash from: #402 (comment):
happens only if at least one other page is included besides page 16. I think it has something to do with these two release calls: Lines 68 to 73 in cda991b
The ASAN doesn't trigger if one call is removed. Does |
What are the two calls that can be removed? What you are describing only makes sense if the line that is removed is |
Yes, that line. No change if the other one is removed.
The docs say:
So if it doesn't allocate anything new in that case, then it shouldn't do it in the other case either? On here, it says:
So: |
Right, it's a double-free. |
Okay, I fixed it in a more correct way than just removing that line. Does asan still complain? |
No 👍 |
9f401b7
to
fb694ed
Compare
In that case, what's left in this PR? |
That double-free was never part of this PR. I think that the same bug also still exists on Linux, this line Line 46 in cda991b
allocates cstride * pixelHeight * 4 = pixelWidth * 4 * pixelHeight * 4 bytes which seems to be 4 times too many.
|
I made a decision // uiImageAppend adds a representation to the uiImage.
// pixels should point to a byte array of non-premultiplied pixels
// stored in [R G B A] order (so ((uint8_t *) pixels)[0] is the R of the
// first pixel and [3] is the A of the first pixel). pixelWidth and
// pixelHeight is the size *in pixels* of the image, and pixelStride is
// the number *of bytes* per row of the pixels array. Therefore,
// pixels itself must be at least pixelStride * pixelHeight bytes long. If libui doesn't follow this, we'll have to fix it. I'll do that before merging. |
All right, this should be resolved now. Thanks again! What's left in this PR to merge in? And I forget if I asked already, but: what cmake/make line are you using to build libui with the sanitizers? I'd like to know so I could do so too. |
Is |
c5c9b81
to
3b13d33
Compare
The macOS uiImageAppend byte "swizzling" would only work for
cd build && cmake .. -DADDRESS_SANITIZER=ON Handled here: Line 129 in cda991b
|
3b13d33
to
7793071
Compare
7793071
to
c0742d3
Compare
All right, thanks. @msink no, that's just what the minimum value of the pixel stride is. What the stride actually is is a question for the person supplying the image data. Perhaps some image decoding library like libpng sets a custom stride. It's a standard parameter when handling raw image data that every library provides either as an input, output, or both, and libui is no different; the point is that some image manipulations can be made faster if the pixels of each scanline are aligned in a way that seems unusual when thinking about the image as strictly a matrix of pixels. |
Done. |
I still not get - anyway internal stride will/can differ from input parameter of But of course I do not insist on anything, just curious. |
That's what I though at first as well.
|
On specific hardware - maybe, so it is internal to libui. |
Ideally there should be no copying — on Windows, there is none; we just give the image data directly to WIC! I'm only providing it because every other API I've seen that deals with raw image data provides it, including the low-level ones libui uses, or it explicitly specifies that the stride is always == Anyway, thanks again! Is the address sanitizer cmake stuff another PR? I'll merge that in (with an explanation of why it needs |
It's already in master (added in 92b860c)? It's just not not documented. The frame-pointer option basically turns off an optimization to create more useful stack traces. Lines 128 to 129 in cda991b
|
Oh. I'm a forgetful dolt sometimes ^^; |
(not sure if the corresponding linux code is correct)