Mir

Merge lp://qastaging/~afrantzis/mir/buffer-native-type into lp://qastaging/mir

Proposed by Alexandros Frantzis
Status: Rejected
Rejected by: Alexandros Frantzis
Proposed branch: lp://qastaging/~afrantzis/mir/buffer-native-type
Merge into: lp://qastaging/mir
Diff against target: 175 lines (+45/-0)
12 files modified
include/platform/mir/graphics/buffer.h (+2/-0)
src/platforms/android/server/buffer.cpp (+5/-0)
src/platforms/android/server/buffer.h (+2/-0)
src/platforms/mesa/server/common/gbm_buffer.cpp (+6/-0)
src/platforms/mesa/server/common/gbm_buffer.h (+2/-0)
src/platforms/mesa/server/common/shm_buffer.cpp (+6/-0)
src/platforms/mesa/server/common/shm_buffer.h (+1/-0)
src/server/compositor/temporary_buffers.cpp (+5/-0)
src/server/compositor/temporary_buffers.h (+1/-0)
tests/include/mir/test/doubles/mock_buffer.h (+1/-0)
tests/include/mir/test/doubles/stub_buffer.h (+5/-0)
tests/unit-tests/compositor/test_temporary_buffers.cpp (+9/-0)
To merge this branch: bzr merge lp://qastaging/~afrantzis/mir/buffer-native-type
Reviewer Review Type Date Requested Status
Kevin DuBois (community) Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+269226@code.qastaging.launchpad.net

Commit message

platform: Introduce the Buffer::native_type() method

Description of the change

platform: Introduce the Buffer::native_type() method

This MP introduces the Buffer::native_type() which returns a pointer to the original buffer object (i.e. the one created by the platform), so that the pointer can be eventually downcast to a renderer specific type. This method is needed since buffer objects can be wrapped by the TemporaryBuffer class, losing the original type information.

To get an idea of how this is going to be used see:
https://code.launchpad.net/~afrantzis/mir/texture-bindable/+merge/269231

Some return types that could have been used, and my reasons for not using them:

void*: It removes the option of dynamic_cast-ing

a new NativeBufferType class: As mentioned above, native_type() is just a workaround to get access to the original type in the presence of wrapping. If we didn't have wrapping we would just cast the original mg::Buffer directly anyway (i.e. we wouldn't have a special base type). Perhaps as we implement more platform/renderers we will find reasons to revisit this decision, but I don't see a need for a special base class at this point.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

Just to represent the mapper approach:

Like, what I had envisioned is (some pseudocode ahead):
mg::Mapper
{
    GLBinding bind_to_gl(std::shared_ptr<NativeBuffer> const&, GLContext&);
    vkImage vulkan_image_from(std::shared_ptr<NativeBuffer> const&);
    MemoryRegion map_to_cpu(std::shared_ptr<NativeBuffer> const&);
}

plus:
mg::Buffer
{
....
    std::shared_ptr<NativeBuffer> native_buffer_handle(); // existing
    mg::BufferUsage[1] usage();
}

and the renderer would look like:

GLRenderer(std::shared_ptr<mg::Mapper> const& mapper) : mapper(mapper) {}
void GLRenderer::render(RenderableList list)
{
   context.make_current();
   for(auto & r : list)
   {
       auto buffer = r->buffer();
       if (buffer->capabilites().has_gl_capability())
           mapper->bind_to_gl_context(buffer->native_buffer_handle(), context);
       //else we're in trouble
   }
   context.swap_buffers();
}

This approach gives us:
GLRenderer() {}
void GLRenderer::render(RenderableList list)
{
   context.make_current();
   for(auto & r : list)
   {
       auto buffer = r->buffer();
       auto bindable = dynamic_cast<TextureBindable>(buffer->native_buffer());
       if (bindable)
            bindable->gl_bind();
       //else we're in trouble
   }
   context.swap_buffers();
}

[1] This currently an enum class, should be more of a bitmask of the capabilities.

I guess though at the end of the day, we still have that "//else we're in trouble" when the capabilities don't match up. We're still stuck throwing when the user tries map an incapable object.

I'd rather communicate the capabilites of the object in an explicit way rather than have to figure out the inheritance structure of the object we have. With this way, the user has to know that a TextureBindable interface exists, and that some mg::Buffers inherit from it, rather than finding an enum, and seeing explicitly if the buffer is capable or not.

Revision history for this message
Kevin DuBois (kdub) wrote :

And, having said all that :) The approaches aren't all that different... and although I guess I'd prefer the bikeshed in the other color... ^_^

With the casting approach, I'd still prefer:

mg::NativeBufferBase* mg::Buffer::native_buffer_base()

that we can then cast to TextureBindable, as it doesn't force all mg::Buffer implementations to inherit from some sort of binding interface, and lets us separate the implementation of the buffers in the platform.

Hmm, what sort of review is that... I guess the above part was just rambling, then a 'needs fixing' just on the return type, which is a smaller change, and would give more flexibility in the structure of the platform Buffer objects.

There's also a bit of a 'needs info' about the plan for mg::Buffer::write, read, gl_bind_to_texture, as those seem redundant on mg::Buffer after the new plan now.

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> I'd rather communicate the capabilites of the object in an explicit way rather
> than have to figure out the inheritance structure of the object we have. With
> this way, the user has to know that a TextureBindable interface exists, and
> that some mg::Buffers inherit from it, rather than finding an enum, and seeing
> explicitly if the buffer is capable or not.

Regardless of the implementation details, I think that our different solutions stem from making different trade-offs in the explicitness/coupling axes for renderer types in our core. I want our core interfaces to know absolutely nothing (minimal coupling) about the different rendering types, so that adding a new renderer type does not involve any Mir changes. A vendor could ship a platform and renderer plugin (with a new renderer type, e.g., "vendor-hw-blitter") and any compatible mir server would just use them transparently. For the common rendering types (for which we are going to provide some default renderer plugins) we are going to ship the interface definitions, so that 3rd party platforms can reuse them.

> With the casting approach, I'd still prefer:
> mg::NativeBufferBase* mg::Buffer::native_buffer_base()

As mentioned, I didn't see an immediate advantage using a new base type vs returning mg::Buffer*, especially since I consider this branch just a workaround for wrapping. However, I am fine with this approach, too (it's actually what I used when I spiked this branch). Let's get some more opinions and if there is a preference for this I will change it.

> There's also a bit of a 'needs info' about the plan for mg::Buffer::write, read,
> gl_bind_to_texture, as those seem redundant on mg::Buffer after the new plan now.

gl_bind_to_texture is moved to a renderer specific interface, used exactly as you have shown in the code example in a previous comment. The proposed branch is:

https://code.launchpad.net/~afrantzis/mir/texture-bindable/+merge/269231

Other renderer specific methods will be handled similarly.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

For the Buffer::native_buffer_base() variation as discussed in a previous comment see:

https://code.launchpad.net/~afrantzis/mir/buffer-native-buffer-base/+merge/269363

Cast your vote!

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Unmerged revisions

2880. By Alexandros Frantzis

platform: Introduce Buffer::native_type() method

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.

Subscribers

People subscribed via source and target branches