Mir

Merge lp:~kdub/mir/overlay-gl-program into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 1660
Proposed branch: lp:~kdub/mir/overlay-gl-program
Merge into: lp:mir
Diff against target: 998 lines (+479/-51)
29 files modified
include/platform/mir/graphics/gl_program.h (+17/-8)
include/platform/mir/graphics/gl_program_factory.h (+2/-1)
include/shared/mir/geometry/point.h (+3/-0)
include/shared/mir/geometry/rectangle.h (+2/-0)
include/test/mir_test_doubles/mock_display_device.h (+1/-1)
include/test/mir_test_doubles/mock_renderable_list_compositor.h (+1/-1)
include/test/mir_test_doubles/stub_gl_program.h (+42/-0)
include/test/mir_test_doubles/stub_gl_program_factory.h (+6/-0)
include/test/mir_test_doubles/stub_renderable.h (+10/-2)
include/test/mir_test_doubles/stub_renderable_list_compositor.h (+1/-1)
src/platform/graphics/android/CMakeLists.txt (+1/-1)
src/platform/graphics/android/display_buffer.cpp (+1/-1)
src/platform/graphics/android/display_buffer.h (+2/-2)
src/platform/graphics/android/fb_device.cpp (+1/-1)
src/platform/graphics/android/hwc_device.cpp (+1/-1)
src/platform/graphics/android/hwc_fallback_gl_renderer.cpp (+86/-9)
src/platform/graphics/android/hwc_fallback_gl_renderer.h (+15/-7)
src/platform/graphics/android/hwc_fb_device.cpp (+1/-1)
src/platform/graphics/gl_program.cpp (+3/-3)
src/server/compositor/gl_renderer.cpp (+1/-1)
src/server/graphics/program_factory.cpp (+9/-1)
src/server/graphics/program_factory.h (+2/-0)
src/shared/geometry/rectangle.cpp (+10/-0)
tests/unit-tests/graphics/android/CMakeLists.txt (+1/-1)
tests/unit-tests/graphics/android/test_fb_device.cpp (+1/-1)
tests/unit-tests/graphics/android/test_hwc_display.cpp (+2/-0)
tests/unit-tests/graphics/android/test_hwc_fallback_gl_renderer.cpp (+254/-6)
tests/unit-tests/graphics/android/test_hwc_fb_device.cpp (+1/-1)
tests/unit-tests/graphics/android/test_output_builder.cpp (+2/-0)
To merge this branch: bzr merge lp:~kdub/mir/overlay-gl-program
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alan Griffiths Approve
Cemil Azizoglu (community) Approve
Alberto Aguirre (community) Approve
Mir development team Pending
Review via email: mp+220690@code.launchpad.net

This proposal supersedes a proposal from 2014-04-24.

Commit message

android: add simple shader program that the android display system will use when the driver rejects the overlays. At the time being, it is just a simple blitter, as we start to support other HWC capabilites like alpha or 90 degree rotation, it will grow, but just a line or two.

Description of the change

android: add simple shader program that the android display system will use when the driver rejects the overlays. At the time being, it is just a simple blitter, as we start to support other HWC capabilites like alpha or 90 degree rotation, it will grow, but just a line or two.

note:
* The HWC is not being used by the platform-independent code. This code can potentially be used in the mir_demo_standalone_render_overlays program.

* I mention this somewhat a lot, but one more time won't hurt. We arrange a list of buffers and submit them to hwc's prepare() function. HWC can choose to accept or reject each buffer as a buffer that it can get to the screen in an optimized way. If the buffer is rejected, we're obliged to use OpenGL to render those buffers to a fb target that is also known to hwc. Although it might seem like we could use something other than OpenGL to draw (perhaps), hwc and OpenGL are pretty intrinsically tied together, doing so would cause driver problems.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

(1) I think there's a little too much redundancy (and regression) between the existing GLRenderer and OverlayGLProgram. It would be better if we made use of the existing GLRenderer so we didn't have to fix the GL rendering logic twice every time we change it. Plus it makes sense that if overlay fails, then "use the GLRenderer you already know that works".

One thing this proposal regresses on is resize support:
295 +GLfloat const texcoords[]{
296 + 0.0f, 0.0f,
297 + 0.0f, 1.0f,
298 + 1.0f, 0.0f,
299 + 1.0f, 1.0f
300 +};
Fixed texcoords means you're regressing on bug 1259887.

(2) This is misleading:
  +void mga::OverlayGLProgram::render(
"program" has a very specific meaning in OpenGL but you are giving a "GLProgram" class fixed-function GL calls. That makes no sense. But also, see (1)

I suggest these changes would be better deferred until there's a real use case for them, because they only create serious maintenance concerns AFAICS right now. And with some more thought, we should fall back to the GLRenderer (or whatever the default renderer is), instead of writing yet another GL renderer.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

In fact, bypass does this already. If bypass fails at any stage it falls back to the GLRenderer. Overlays should do that too.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

There's a lack of role clarity about our various GL classes but I don't mind a little duplication now if it gets factored out later.

OTOH Daniel makes a good point about GL "program".

review: Abstain
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote : Posted in a previous version of this proposal

What is being rendered is "overlay rejects" and once rejected by the hwc, there is nothing "overlay" about them. These renderables should no longer be considered overlays, and the code to render them should not be called a name with the word "overlay" in it (unless it's overlay_rejects or smth that makes it clear that they are not overlays) for the sake of clarity. I see that there is code that already made it in, like render_gl_and_overlays, which I think is confusing and should be cleaned up in time.

For these rejects, I think it'd be nice to find a way to fall back to the usual path (I know you had some concerns about it, though). This may be a good time to factor things out of GLRenderer to make it reuseable. But I don't have an issue with a little bit of duplication if we want to wait for "role clarity", as Alan put it.

review: Needs Fixing
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

> What is being rendered is "overlay rejects" and once rejected by the hwc,
> there is nothing "overlay" about them. These renderables should no longer be
> considered overlays, and the code to render them should not be called a name
> with the word "overlay" in it (unless it's overlay_rejects or smth that makes
> it clear that they are not overlays) for the sake of clarity. I see that there
> is code that already made it in, like render_gl_and_overlays, which I think is
> confusing and should be cleaned up in time.

We chose this "list of surfaces to overlay" approach to avoid 2-way communication between the GL renderer (may not be Mir's GLRenderer remember) and the HWC code. This is especially important for case of nested server where a return message of "these surfaces were rejected by the hwc, so do it yourself" would be costly. From the shell point of view, the fire and forget approach is easier.

I also prefer having the simple OverlayGLProgram as the GL fallback, instead of the more resource heavy GLRenderer.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> What is being rendered is "overlay rejects" and once rejected by the hwc,
> there is nothing "overlay" about them. These renderables should no longer be
> considered overlays, and the code to render them should not be called a name
> with the word "overlay" in it (unless it's overlay_rejects or smth that makes
> it clear that they are not overlays) for the sake of clarity. I see that there
> is code that already made it in, like render_gl_and_overlays, which I think is
> confusing and should be cleaned up in time.

'and once rejected by the hwc, there is nothing "overlay" about them"
From the DefaultDisplayBufferCompositor's perspective, it was still a surface that was accepted as a hardware optimization, its a quirk of the HWC api that we actually do some of the rendering with GL.

There is a subtle, yet distinct difference between a mg::Renderable and an android overlay.

A list of mg::Renderable can do things that a list of hwc_display_contents_1 cannot.
The android code has a fixed function that it is expected to perform as a matter of HWC api.
RenderableList is the list that we can expand to do what we want our most advanced GL compositors to do. Some more concrete examples are that the HWC api expects an orthogonal projection, the RenderableList can use any perspective it wants. The RenderableList could potentially model things like a blur effect (or something) that the hwc would have no idea about. The RenderableList can set arbitrary transforms with arbitrarily tessellated surfaces, android can only support a 90degree rotation., etc.

The android code will take the more universal list and reject that list to the DisplayBufferCompositor if the RenderableList has a requirement that the HWC cannot optimize.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

As for the "reuse or not to reuse" I considered this, and decided in favor of adding a very simple program like this.

1) Tying parts of the GLRenderer to the android-specific fallback renderer makes the GLRenderer parts not as malleable; they have to support the hard requirements that the Android fallback needs. I fear that a future bug-fixer or feature-implementer might not realize that changing GLRenderer stuff might break the hard requirements that this GL program has.

2) We might want to do something in the android shader that we doesn't have a concept in GLRenderer, like 'desaturate GPU-renderered regions for debugging purposes"

3) The duplication is really just the most primitive things a shader program can do; we either have 1 shader to rule them all or we have 'duplication' of lines like "gl_FragColor = texture2D(tex, v_texcoord);\n". I'd rather hedge on having different programs fulfilling the role we need them to fulfill as opposed to trying to have one program that we fit in different roles.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> (1) I think there's a little too much redundancy (and regression) between the
> existing GLRenderer and OverlayGLProgram. It would be better if we made use of
> the existing GLRenderer so we didn't have to fix the GL rendering logic twice
> every time we change it. Plus it makes sense that if overlay fails, then "use
> the GLRenderer you already know that works".

My concern is that I don't have to fix the Android program any time that renderable expands in a way that causes problems for the requirements that this code needs to support as a matter of the HWC api. I want to let the 'universal, platform-independant, flexible renderer" (the GLRenderer) be malleable while we try to solve those problems, while the android 'do-what-HWC-commands-me-to-do renderer" stays fixed, and abstracted from the code up in libmirserver.so

> One thing this proposal regresses on is resize support:
> 295 +GLfloat const texcoords[]{
> 296 + 0.0f, 0.0f,
> 297 + 0.0f, 1.0f,
> 298 + 1.0f, 0.0f,
> 299 + 1.0f, 1.0f
> 300 +};
> Fixed texcoords means you're regressing on bug 1259887.

Interesting, although its an exercise in the definition of 'regression' to figure out if new code with a new purpose can regress. It also points out another difference in the RenderableList and the hwc_contents_1_t list, which is that the hwc list defines position by the top-left corner, and the Renderable::transformation is a center-based positioning. This is a bit difficult to make sure that this doesn't have visual effects at the moment, because its not hooked up all the way through. I'll make sure to test this (hwc overlay+resize is giving me some other problems in my yet-proposed branches)

>
> (2) This is misleading:
> +void mga::OverlayGLProgram::render(
> "program" has a very specific meaning in OpenGL but you are giving a
> "GLProgram" class fixed-function GL calls. That makes no sense. But also, see
> (1)

ack, will think of new naming.

>
> I suggest these changes would be better deferred until there's a real use case
> for them, because they only create serious maintenance concerns AFAICS right
> now. And with some more thought, we should fall back to the GLRenderer (or
> whatever the default renderer is), instead of writing yet another GL renderer.

The real use-case right now is the mir_demo_standalone_render_overlays, which won't render anything in some cases, depending on driver behavior. This will be hooked up in later reviews, but I thought I'd propose this now, as it seemed like a pretty contained MP. The android platform is a bit strange in that it needs this GL functionality to render overlays sometimes. I want the quirk of the android platform to be abstracted as much as we possible from the GLRenderer/DisplayBufferCompositor code.

Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote : Posted in a previous version of this proposal

Ok I understand the GLRenderer can get arbitrarily elaborate and it may not be a good idea to use the same objects/shaders to render both. I'm all for KISS! Also, I think you're saying GLRenderer could be replaced but "overlay rendering" (now I'm using the term that I said I didnt like) cannot, and making them share code might cause problems for those that want to replace the GLRenderer. Understood.

You said you'd change the class name above. Could we find a different designation for these surfaces once they 've been rejected as overlays.

Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote : Posted in a previous version of this proposal

AFAIS the this fallback renderer is not replaceable. This means that we 'd be requiring GL capable GPU once this code is merged. To me, it's okay, Android has required it for a couple of years now. But since GLRenderer is replaceable, perhaps there was a discussion/expectation that things would work without GL. So I wanted to explicitly state this.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> AFAIS the this fallback renderer is not replaceable. This means that we 'd be
> requiring GL capable GPU once this code is merged. To me, it's okay, Android
> has required it for a couple of years now. But since GLRenderer is
> replaceable, perhaps there was a discussion/expectation that things would work
> without GL. So I wanted to explicitly state this.

Right, a GL capable gpu, but really just for the android platform. We also have further detanglement to do in mg::DisplayBuffer if we ever get a non-GL/EGL platform.

Still thinking on the naming, but I think its good to make the distinction of 'overlays' just in the android platform, and, within the android platform, to classify by 'overlay' or by 'fallback rendered' based on the result of prepare()

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Can we establish what's wrong with GLRenderer? In theory it's going to be much faster (e.g. has texture caching), less buggy (e.g. the texcoords) and more featured (e.g. has screen rotation) than what's presented here. Using GLRenderer is not only faster, less buggy and more featured, but also halves maintenance effort.

GLRenderer appears to win at every point. So if anyone thinks it's heavy-weight then please point out where and we'll fix it.

Revision history for this message
Alberto Aguirre (albaguirre) wrote : Posted in a previous version of this proposal

OverlayCompositor and OverlayGLProgram,

maybe
HWCFallbackCompositor, HWCFallbackRenderer?

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> Can we establish what's wrong with GLRenderer? In theory it's going to be much
> faster (e.g. has texture caching), less buggy (e.g. the texcoords) and more
> featured (e.g. has screen rotation) than what's presented here. Using
> GLRenderer is not only faster, less buggy and more featured, but also halves
> maintenance effort.
>
> GLRenderer appears to win at every point. So if anyone thinks it's heavy-
> weight then please point out where and we'll fix it.

Right, so nothing is wrong with GLRenderer, but we do have difference in what we require the two programs to do. We have marching orders to make GLRenderer+QtSG the next-gen full featured composition system (that is also the USC renderer); something that is much more than the requirements HWC gives us to implement the overlay functionality.

Writing a second program is a bit of a judgement call and the upsides are that the GLRenderer can grow and flex without having to fulfill the "be the full-featured next generation advanced OpenGL compositor" requirement while still having to fulfill the fixed requirements of HWC. GLRenderer can just grow to be the advanced compositor we want it to be. I'd agree with the half the maintenence effort if this was an open-ended program, but its not. This program has a very small fixed set of things it has to do, so the road to the perfect HWC program is short and unambiguous.

GLRenderer still has a fair amount of expansion that we'll build upon, and we'll isolate this fallback path from any changes to that class. (changes that would only hit the android platform as bugs). I'm worried that we'll go to implement something like an animation system (on the desktop) and inadvertently cause rendering problems on android, problems that would only occur in fallback scenarios.

I think a decent compromise is to:
1) maintain the second small program in the android platform, so we can let GLRenderer grow and isolate this platform-specific GL requirement from any changes there.
2) tease out mc::GLRenderer::tessellate() (and perhaps other universal functionality) from GLRenderer so there's more code re-use.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I'm concerned that we're going to have to fix everything twice. And in fact fix things that aren't yet broken, like resizing and rotation. Delegating blame of such issues to just say it only affects overlays is one thing, but fixing regressions will occupy more time than not having to fix regressions.

Also consider this: Most shells will presumably be built on OpenGL at some level. So unless you always have a fullscreen app open part of the shell will be visible. And if part of the shell is visible then you already have to do some GL rendering on that frame. And if you already have to GLRender on that frame, why not use the GLRenderer that is already going to be used for other elements in that frame anyway?

I share your fears (and some excitement) for the growth of GLRenderer. But we are capable of breaking it up and modularization. Having thought about animation a lot in the past year, if I believed it should be strictly wired into the renderer then I would have proposed it already (the design is mostly done in my head). However I too want to be cautious about how much responsibility the core default GLRenderer has.

On the issue of tessellate(), that's an interesting one. Because tessellate() is a strictly OpenGL-specific operation. Not just in its implementation, but the concept only makes sense to OpenGL in my experience. And having to produce only triangles is unfortunately a requirement only for the ES variation of OpenGL.

Revision history for this message
Alberto Aguirre (albaguirre) wrote : Posted in a previous version of this proposal

I think I'm convinced that it should be a separate program.

However it should be a very simple fallback - that is no resize support and no handling of screen rotation; I believe what is proposed here satisfies that.

If those features are needed, then it should fallback to the path we currently have (with GLRenderer).

So: hwc->prepare(..)
If all layers accepted - great - nothing else to do.
If some layers got rejected and need screen rotation/resizing - fallback to GLRenderer path - composite all layers with GLRenderer - essentially the path we use currently.
Otherwise fallback so simple hwc fallback GL compositor.

Needs fixing:
OverlayGLProgram - my suggestion is HWCFallbackGLRenderer to make it real clear what is responsiblity is.
OverlayCompositor - like Cemil says once rejected they are not "overlays" per se. So my suggestions is HWCFallbackCompositor

review: Needs Information
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote : Posted in a previous version of this proposal

+1 on the names Alberto is proposing.

I think things will get interesting when YUV support is eventually added. Hopefully display overlay will support the format so hwc will not reject it. But if it does, it's almost certain that resize will be needed - video dimensions almost never match player's viewing area. Also, rotation should be supported IMHO, too.

Why not use the "replaceable renderer"? (I'm not calling it GLRenderer on purpose). It may not be capable of handling YUV due to, perhaps, hardware limitations on the format/surface/stride. Or it may not be desirable to use the specific GPU resource powering the "replaceable renderer". For instance for an extremely power efficient device operation, the replaceable renderer could be powered by a blitter, only on occasion falling back to 3D GPU. So the replaceable renderer could go either way - more fully fledged, or dumber. Whereas the hwc fallback renderer always have a very well-defined task to do.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

So the specific thing that happened to me when I was developing was I was tinkering with the demo shell on the adreno nexus 7, and the driver optimized the render by clipping the pixels outside of the bounding box of the hwc_layer_1_t. (pushed out less pixels) Since the demo shell clears to grey, and the HWC api guarantees a black background, this made the image on the screen cleared to grey within the bounding box, and cleared to black outside the bounding box.

Now, this is 'valid' HWC behavior, as they only have to guarantee what was sent to the driver in prepare() makes it to the screen, but it is not valid OpenGL behavior.

Furthermore, an extra level of insidious-ness about this discrepancy is that only certain devices running under certain modes might step outside of the OpenGL box and rely on the less-universal requirements of HWC to try some optimization.

So, I'm more nervous about situations where doing something reasonable in GLRenderer (like setting a non-black background color) cause rendering glitches on specific devices, running under specific modes, only when the driver chooses to reject the overlay surface.

I'm less nervous about the task of setting up and maintaining a GL shader program that fulfills the requirements of HWC to the letter, and isolates GLRenderer/common gl code from the weirdness of HWC. The program will just do the basic stuff HWC needs (2D positioning, 90 degree rotation, cropping)

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> +1 on the names Alberto is proposing.
>
> I think things will get interesting when YUV support is eventually added.
> Hopefully display overlay will support the format so hwc will not reject it.
> But if it does, it's almost certain that resize will be needed - video
> dimensions almost never match player's viewing area. Also, rotation should be
> supported IMHO, too.

I'm starting out with just the simple non-scaled, non-rotated, non-alpha blended stuff, and then I'll roll out alpha, and 90deg rotation, etc after some testing focused on those features. But yes, rotation is something that should be supported.

>
> Why not use the "replaceable renderer"? (I'm not calling it GLRenderer on
> purpose). It may not be capable of handling YUV due to, perhaps, hardware
> limitations on the format/surface/stride. Or it may not be desirable to use
> the specific GPU resource powering the "replaceable renderer". For instance
> for an extremely power efficient device operation, the replaceable renderer
> could be powered by a blitter, only on occasion falling back to 3D GPU. So the
> replaceable renderer could go either way - more fully fledged, or dumber.
> Whereas the hwc fallback renderer always have a very well-defined task to do.

YUV is interesting, and I saw that it got much more public support in HWC 1.3. (previously there were hacks behind the scenes iirc). It might be another place where we might have to mix some 'android-standard' approaches with the 'universal OpenGL' approach. There is a fair amount of plumbing in mir (libmirserver and libmirclient) that we have to do before YUV surfaces can get to the compositor though.

Revision history for this message
Alberto Aguirre (albaguirre) wrote : Posted in a previous version of this proposal

> I'm starting out with just the simple non-scaled, non-rotated, non-alpha
> blended stuff, and then I'll roll out alpha, and 90deg rotation, etc after
> some testing focused on those features. But yes, rotation is something that
> should be supported.
>

That's my point though, if you punt to the GLRenderer (for ALL layers even if only one is rejected)
then there's no need to implement those features and the HWC Fallback renderer can remain very simple.

Revision history for this message
Alberto Aguirre (albaguirre) wrote : Posted in a previous version of this proposal

> > I'm starting out with just the simple non-scaled, non-rotated, non-alpha
> > blended stuff, and then I'll roll out alpha, and 90deg rotation, etc after
> > some testing focused on those features. But yes, rotation is something that
> > should be supported.
> >
>
> That's my point though, if you punt to the GLRenderer (for ALL layers even if
> only one is rejected)
> then there's no need to implement those features and the HWC Fallback renderer
> can remain very simple.

I mean punt when layers are rejected and any of the rejected layers needs resizing, rotation etc...

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

so hopefully the naming should be addressed. "OverlayCompositor" was just the name of the test. The class and the test are now "HWCFallbackGLRenderer", as matching the class name to the test name seems less confusing/more consistent.

Still working on addressing the outstanding points, probably won't get them out the door today(4/30)

Revision history for this message
Alberto Aguirre (albaguirre) wrote : Posted in a previous version of this proposal

In any case this first simple version looks good to me.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Even if it is justified in introducing a new code path, I think we can still do a bit better in avoiding the very familiar duplication inside mga::HWCFallbackGLRenderer::render().

The first part of that (which I had hoped to do anyway) is to pass Renderer::render() the full list. Then the various render() functions start to look even more similar. And as such it will become easier to avoid duplicate code.

I'm not quite convinced enough yet. Because I think there is simple work we can do relatively quickly to reduce the duplication (and ideally avoid regressions landing).

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal
Download full text (4.6 KiB)

> Even if it is justified in introducing a new code path, I think we can still
> do a bit better in avoiding the very familiar duplication inside
> mga::HWCFallbackGLRenderer::render().
>
> The first part of that (which I had hoped to do anyway) is to pass
> Renderer::render() the full list. Then the various render() functions start to
> look even more similar. And as such it will become easier to avoid duplicate
> code.

Given my thoughts about the quirks of HWC/OpenGL interplay, some object in the system must be the hardware-specific HWC renderer. It must play by the OpenGL+HWC limitations. There exists some other item in the system that can do full opengl, that the user can override, and can expand in whatever way we see fit. So the unresolved question is "is this second item a private instance of the GLRenderer?"

I would still say there's a good case to have something different:

1) although I have in rev1585:
void mga::HWCFallbackGLRenderer::render(RenderableList const& renderlist, SwappingGLContext const& context)
this really should be render(hwc_display_contents_1_t const&, SwappingGLContext). The Renderable's are just used now because I haven't made a way for the HWCLayers to return their associated buffers yet. Its convenient, albeit a bit fragile because the implementation has to use only the 'hwc-compatible' functions on Renderable.
1a) A Renderable is a superset of the information that a hwc_layer_1_t is. We could limit the GLRenderer to what the hwc_layer_1_t can do, or we can have the GLRenderer do more than what the hwc requires. It seems better to just let them evolve on their own path, especially as one requirement is platform-specific.

2) The requirement that the rejected overlays should be drawn via OpenGL is a quirk of the Android platform. Having a non-overridable OpenGL+HWC-restricted program in the platform-independent server code breaks the platform-independence in a worse way than allowing the platforms to compile their own gl programs. The platform independent libmirserver code has to respect specific guidelines set by the android platform, even if those requirements are tangled up in OpenGL.

3) In the same sort of vein, the object that supports this android quirk, and the object that is the platform-independent default renderer will take different paths. The have a fair amount of overlap in their current states, but we really do intend divergence in their responsibilities. The android stuff will evolve into deeper support of the lower-level optimizations (like, 'flash GL regions", YUV/color processing) and the platform-independent default renderer will evolve to support advanced shell stuff (animations, blurs, etc etc).

4) Splitting the two also lets us keep the interesting GLRenderer stuff GPL and the simplistic android stuff LGPL. Without getting too a head of myself, this could ease working with vendors when/if we come hwc extension agreements after working with them.

Now, having said all that :) The opposing point about code reuse is valid, and I can share some of the code by teasing it out of GLRenderer. I'm envisioning a smallish LGPL header with ways to do 1) texture caching 2) tessellation 3) texcood c...

Read more...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote : Posted in a previous version of this proposal

Happy with the names.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

(1) Still too much redundancy. And I don't think designing in regressions is OK, unless we agree no one is ever going to use the overlays path. We don't have to resolve this by inheriting from or calling GLRenderer necessarily. The various *GLRenderer's could call some common code that contains the shared logic.

(3) This class name is too long and also misleading - SingleVertexSingleFragmentProgram. A "single vertex" or "single fragment" program sounds too much like something designed to render 1x1 pixel points only, which is obviously untrue. Rendering anything that's not a point of course requires multiple vertices and many fragments (which is actually what it does). Something like "SimpleGLProgram" would be more accurate.

(4) Can you tease apart the proposal into smaller chunks? I suspect that might make it easier to manage...

review: Needs Fixing
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

2)
Sure, can address the naming. OneVertexShaderOneFragmentShaderProgram is too long, so SimpleGLProgram is okay.

1)
I haven't had as much time to work on splitting out the code this week as I'd have liked, but I do plan on reusing some of the various GLRenderer calls. Specifically, the texture caching, and the texcoord calculation. I can get these out the door before this lands so the reuse plan is more visible.

3)
I was thinking that anything less would might be hard to review from "dont see the big picture" argument.
This chunk of code is what I deemed the minimal amount that will get something sensible in this place, and less code would be difficult to figure out what I'm trying to do. Maybe I can break out the changes to the Rectangle eg, top_right(), or the interface changes (which were largely test-driven)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> I haven't had as much time to work on splitting out the code this week as I'd
> have liked, but I do plan on reusing some of the various GLRenderer calls.
> Specifically, the texture caching, and the texcoord calculation. I can get
> these out the door before this lands so the reuse plan is more visible.

I still want to chew on the naming before mp-ing, but split out the texture caching here: lp:~kdub/mir/reusable-texture-cache. Will get to the texcoord stuff tomorrow, and rebase on those.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

There's also lp:~kdub/mir/reusable-quad-calculation that this branch can pick up to increase the amount of code reuse between the two programs. Hopefully those two branches address some of the reused code concerns.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

Since this is now based on two branches resubmitting with a prerequisite branch would still give too big of a diff. Maintaining the merge of the branches here: lp:~kdub/mir/overlay-gl-program-with-reuse , which I will merge into this branch once the prereqs land.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

diff should reduce once the landing queue clears

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Oh, good work keeping this branch up to date with the other landings.

I note that the current Approvals however are based on a much older and significantly version. So I think the current Approvals need to be invalidated by resubmitting the proposal.

review: Needs Resubmitting
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

151 + return 7;

Magic?

~~~~

790 +// EXPECT_CALL(mock_gl, glGenTextures(1,_));

Useless code or useless comment - either way it is useless.

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

@Daniel,
resubmitted.

@Alan,
not a magic number, just a valid number that the stub could return.
comment removed.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

~~
151 + return 7;
~~
Perhaps:
int const arbitrary_id = 7;
return arbitrary_id;

Looks good.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

LGTM

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

OK

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/platform/mir/graphics/gl_program.h'
2--- include/platform/mir/graphics/gl_program.h 2014-05-07 02:56:33 +0000
3+++ include/platform/mir/graphics/gl_program.h 2014-05-22 16:51:59 +0000
4@@ -43,17 +43,26 @@
5 class GLProgram
6 {
7 public:
8- GLProgram(
9+ virtual ~GLProgram() = default;
10+ virtual operator GLuint() const = 0;
11+
12+protected:
13+ GLProgram() = default;
14+private:
15+ GLProgram(GLProgram const&) = delete;
16+ GLProgram& operator=(GLProgram const&) = delete;
17+};
18+
19+class SimpleGLProgram : public GLProgram
20+{
21+public:
22+ SimpleGLProgram(
23 GLchar const* vertex_shader_src,
24 GLchar const* fragment_shader_src);
25- ~GLProgram();
26-
27- operator GLuint() const;
28-
29+ ~SimpleGLProgram();
30+
31+ operator GLuint() const override;
32 private:
33- GLProgram(GLProgram const&) = delete;
34- GLProgram& operator=(GLProgram const&) = delete;
35-
36 GLShader const vertex_shader;
37 GLShader const fragment_shader;
38 GLuint const program;
39
40=== modified file 'include/platform/mir/graphics/gl_program_factory.h'
41--- include/platform/mir/graphics/gl_program_factory.h 2014-04-22 16:45:27 +0000
42+++ include/platform/mir/graphics/gl_program_factory.h 2014-05-22 16:51:59 +0000
43@@ -20,6 +20,7 @@
44 #define MIR_COMPOSITOR_GL_PROGRAM_FACTORY_H_
45
46 #include "mir/graphics/gl_program.h"
47+#include "mir/graphics/gl_texture_cache.h"
48 #include <memory>
49
50 namespace mir
51@@ -34,7 +35,7 @@
52
53 virtual std::unique_ptr<GLProgram>
54 create_gl_program(std::string const&, std::string const&) const = 0;
55-
56+ virtual std::unique_ptr<GLTextureCache> create_texture_cache() const = 0;
57 protected:
58 GLProgramFactory() = default;
59
60
61=== modified file 'include/shared/mir/geometry/point.h'
62--- include/shared/mir/geometry/point.h 2014-03-06 06:05:17 +0000
63+++ include/shared/mir/geometry/point.h 2014-05-22 16:51:59 +0000
64@@ -50,6 +50,9 @@
65 return lhs.x != rhs.x || lhs.y != rhs.y;
66 }
67
68+inline Point operator+(Point lhs, DeltaX rhs) { return{lhs.x + rhs, lhs.y}; }
69+inline Point operator+(Point lhs, DeltaY rhs) { return{lhs.x, lhs.y + rhs}; }
70+
71 std::ostream& operator<<(std::ostream& out, Point const& value);
72 }
73 }
74
75=== modified file 'include/shared/mir/geometry/rectangle.h'
76--- include/shared/mir/geometry/rectangle.h 2014-03-06 06:05:17 +0000
77+++ include/shared/mir/geometry/rectangle.h 2014-05-22 16:51:59 +0000
78@@ -42,6 +42,8 @@
79 * area, that is, the rectangle is represented as [top_left,bottom_right).
80 */
81 Point bottom_right() const;
82+ Point top_right() const;
83+ Point bottom_left() const;
84 bool contains(Point const& p) const;
85
86 /**
87
88=== modified file 'include/test/mir_test_doubles/mock_display_device.h'
89--- include/test/mir_test_doubles/mock_display_device.h 2014-05-19 02:55:29 +0000
90+++ include/test/mir_test_doubles/mock_display_device.h 2014-05-22 16:51:59 +0000
91@@ -22,7 +22,7 @@
92 #include "mir/graphics/buffer.h"
93 #include "src/platform/graphics/android/display_device.h"
94 #include "src/platform/graphics/android/gl_context.h"
95-#include "src/platform/graphics/android/overlay_gl_compositor.h"
96+#include "src/platform/graphics/android/hwc_fallback_gl_renderer.h"
97 #include <gmock/gmock.h>
98
99 namespace mir
100
101=== modified file 'include/test/mir_test_doubles/mock_renderable_list_compositor.h'
102--- include/test/mir_test_doubles/mock_renderable_list_compositor.h 2014-04-30 18:26:29 +0000
103+++ include/test/mir_test_doubles/mock_renderable_list_compositor.h 2014-05-22 16:51:59 +0000
104@@ -19,7 +19,7 @@
105 #ifndef MIR_TEST_DOUBLES_MOCK_RENDERABLE_LIST_COMPOSITOR_H_
106 #define MIR_TEST_DOUBLES_MOCK_RENDERABLE_LIST_COMPOSITOR_H_
107
108-#include "src/platform/graphics/android/overlay_gl_compositor.h"
109+#include "src/platform/graphics/android/hwc_fallback_gl_renderer.h"
110 #include <gmock/gmock.h>
111
112 namespace mir
113
114=== added file 'include/test/mir_test_doubles/stub_gl_program.h'
115--- include/test/mir_test_doubles/stub_gl_program.h 1970-01-01 00:00:00 +0000
116+++ include/test/mir_test_doubles/stub_gl_program.h 2014-05-22 16:51:59 +0000
117@@ -0,0 +1,42 @@
118+/*
119+ * Copyright © 2014 Canonical Ltd.
120+ *
121+ * This program is free software: you can redistribute it and/or modify it
122+ * under the terms of the GNU General Public License version 3,
123+ * as published by the Free Software Foundation.
124+ *
125+ * This program is distributed in the hope that it will be useful,
126+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
127+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
128+ * GNU General Public License for more details.
129+ *
130+ * You should have received a copy of the GNU General Public License
131+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
132+ *
133+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
134+ */
135+#ifndef MIR_TEST_DOUBLES_STUB_GL_PROGRAM_H_
136+#define MIR_TEST_DOUBLES_STUB_GL_PROGRAM_H_
137+
138+#include "mir/graphics/gl_program_factory.h"
139+
140+namespace mir
141+{
142+namespace test
143+{
144+namespace doubles
145+{
146+
147+struct StubGLProgram : public graphics::GLProgram
148+{
149+ operator GLuint() const override
150+ {
151+ return 7;
152+ }
153+};
154+
155+}
156+}
157+} // namespace mir
158+
159+#endif /* MIR_TEST_DOUBLES_STUB_GL_PROGRAM_H_ */
160
161=== modified file 'include/test/mir_test_doubles/stub_gl_program_factory.h'
162--- include/test/mir_test_doubles/stub_gl_program_factory.h 2014-04-24 20:07:20 +0000
163+++ include/test/mir_test_doubles/stub_gl_program_factory.h 2014-05-22 16:51:59 +0000
164@@ -19,6 +19,7 @@
165 #define MIR_TEST_DOUBLES_STUB_GL_PROGRAM_FACTORY_H_
166
167 #include "mir/graphics/gl_program_factory.h"
168+#include "stub_gl_program.h"
169
170 namespace mir
171 {
172@@ -32,6 +33,11 @@
173 public:
174 std::unique_ptr<graphics::GLProgram> create_gl_program(std::string const&, std::string const&) const
175 {
176+ return std::unique_ptr<graphics::GLProgram>(new StubGLProgram);
177+ }
178+
179+ std::unique_ptr<graphics::GLTextureCache> create_texture_cache() const
180+ {
181 return nullptr;
182 }
183 };
184
185=== modified file 'include/test/mir_test_doubles/stub_renderable.h'
186--- include/test/mir_test_doubles/stub_renderable.h 2014-05-07 02:56:33 +0000
187+++ include/test/mir_test_doubles/stub_renderable.h 2014-05-22 16:51:59 +0000
188@@ -33,13 +33,20 @@
189 class StubRenderable : public graphics::Renderable
190 {
191 public:
192+ StubRenderable(geometry::Rectangle const& rect)
193+ : rect(rect)
194+ {}
195+ StubRenderable() :
196+ StubRenderable({{},{}})
197+ {}
198 ID id() const override
199 {
200 return this;
201 }
202 std::shared_ptr<graphics::Buffer> buffer() const override
203 {
204- return std::make_shared<StubBuffer>();
205+ graphics::BufferProperties prop{rect.size, mir_pixel_format_abgr_8888, graphics::BufferUsage::hardware};
206+ return std::make_shared<StubBuffer>(prop);
207 }
208 bool alpha_enabled() const
209 {
210@@ -47,7 +54,7 @@
211 }
212 geometry::Rectangle screen_position() const
213 {
214- return {{},{}};
215+ return rect;
216 }
217 float alpha() const override
218 {
219@@ -73,6 +80,7 @@
220
221 private:
222 glm::mat4 trans;
223+ geometry::Rectangle const rect;
224 };
225
226 }
227
228=== modified file 'include/test/mir_test_doubles/stub_renderable_list_compositor.h'
229--- include/test/mir_test_doubles/stub_renderable_list_compositor.h 2014-04-30 18:26:29 +0000
230+++ include/test/mir_test_doubles/stub_renderable_list_compositor.h 2014-05-22 16:51:59 +0000
231@@ -19,7 +19,7 @@
232 #ifndef MIR_TEST_DOUBLES_STUB_RENDERABLE_LIST_COMPOSITOR_H_
233 #define MIR_TEST_DOUBLES_STUB_RENDERABLE_LIST_COMPOSITOR_H_
234
235-#include "src/platform/graphics/android/overlay_gl_compositor.h"
236+#include "src/platform/graphics/android/hwc_fallback_gl_renderer.h"
237
238 namespace mir
239 {
240
241=== modified file 'src/platform/graphics/android/CMakeLists.txt'
242--- src/platform/graphics/android/CMakeLists.txt 2014-05-22 11:31:21 +0000
243+++ src/platform/graphics/android/CMakeLists.txt 2014-05-22 16:51:59 +0000
244@@ -36,7 +36,7 @@
245 gl_context.cpp
246 device_quirks.cpp
247 real_hwc_wrapper.cpp
248- overlay_gl_compositor.cpp
249+ hwc_fallback_gl_renderer.cpp
250 )
251
252 set_target_properties(
253
254=== modified file 'src/platform/graphics/android/display_buffer.cpp'
255--- src/platform/graphics/android/display_buffer.cpp 2014-05-22 11:31:21 +0000
256+++ src/platform/graphics/android/display_buffer.cpp 2014-05-22 16:51:59 +0000
257@@ -62,7 +62,7 @@
258 display_device{display_device},
259 native_window{native_window},
260 gl_context{shared_gl_context, std::bind(mga::create_window_surface, std::placeholders::_1, std::placeholders::_2, native_window.get())},
261- overlay_program{program_factory, gl_context},
262+ overlay_program{program_factory, gl_context, geom::Rectangle{{0,0},fb_bundle->fb_size()}},
263 current_configuration{
264 mg::DisplayConfigurationOutputId{1},
265 mg::DisplayConfigurationCardId{0},
266
267=== modified file 'src/platform/graphics/android/display_buffer.h'
268--- src/platform/graphics/android/display_buffer.h 2014-05-22 11:31:21 +0000
269+++ src/platform/graphics/android/display_buffer.h 2014-05-22 16:51:59 +0000
270@@ -24,7 +24,7 @@
271 #include "mir/graphics/gl_program_factory.h"
272 #include "android_display_configuration.h"
273 #include "gl_context.h"
274-#include "overlay_gl_compositor.h"
275+#include "hwc_fallback_gl_renderer.h"
276 #include <system/window.h>
277
278 namespace mir
279@@ -65,7 +65,7 @@
280 std::shared_ptr<DisplayDevice> const display_device;
281 std::shared_ptr<ANativeWindow> const native_window;
282 GLContext gl_context;
283- OverlayGLProgram overlay_program;
284+ HWCFallbackGLRenderer overlay_program;
285 bool prepared;
286 DisplayConfigurationOutput current_configuration;
287 MirOrientation rotation;
288
289=== modified file 'src/platform/graphics/android/fb_device.cpp'
290--- src/platform/graphics/android/fb_device.cpp 2014-05-19 02:55:29 +0000
291+++ src/platform/graphics/android/fb_device.cpp 2014-05-22 16:51:59 +0000
292@@ -24,7 +24,7 @@
293 #include "fb_device.h"
294 #include "framebuffer_bundle.h"
295 #include "buffer.h"
296-#include "overlay_gl_compositor.h"
297+#include "hwc_fallback_gl_renderer.h"
298
299 #include <boost/throw_exception.hpp>
300 #include <stdexcept>
301
302=== modified file 'src/platform/graphics/android/hwc_device.cpp'
303--- src/platform/graphics/android/hwc_device.cpp 2014-05-19 02:55:29 +0000
304+++ src/platform/graphics/android/hwc_device.cpp 2014-05-22 16:51:59 +0000
305@@ -24,7 +24,7 @@
306 #include "hwc_wrapper.h"
307 #include "framebuffer_bundle.h"
308 #include "buffer.h"
309-#include "overlay_gl_compositor.h"
310+#include "hwc_fallback_gl_renderer.h"
311
312 namespace mg = mir::graphics;
313 namespace mga=mir::graphics::android;
314
315=== renamed file 'src/platform/graphics/android/overlay_gl_compositor.cpp' => 'src/platform/graphics/android/hwc_fallback_gl_renderer.cpp'
316--- src/platform/graphics/android/overlay_gl_compositor.cpp 2014-05-19 02:55:29 +0000
317+++ src/platform/graphics/android/hwc_fallback_gl_renderer.cpp 2014-05-22 16:51:59 +0000
318@@ -18,36 +18,113 @@
319
320 #include "mir/graphics/gl_program_factory.h"
321 #include "mir/graphics/gl_context.h"
322-#include "overlay_gl_compositor.h"
323+#include "mir/graphics/gl_texture.h"
324+#include "mir/graphics/tessellation_helpers.h"
325+#include "hwc_fallback_gl_renderer.h"
326+#include "gl_context.h"
327+#include "buffer.h"
328+
329+#define GLM_FORCE_RADIANS
330+#define GLM_PRECISION_MEDIUMP_FLOAT
331+#include <glm/glm.hpp>
332+#include <glm/gtc/matrix_transform.hpp>
333+#include <glm/gtc/type_ptr.hpp>
334
335 namespace mg = mir::graphics;
336 namespace mga = mir::graphics::android;
337+namespace geom = mir::geometry;
338+
339 namespace
340 {
341 std::string const vertex_shader
342 {
343- "attribute vec4 position;\n"
344+ "attribute vec3 position;\n"
345+ "attribute vec2 texcoord;\n"
346+ "uniform mat4 display_transform;\n"
347+ "varying vec2 v_texcoord;\n"
348 "void main() {\n"
349- " gl_Position = position;\n"
350+ " gl_Position = display_transform * vec4(position, 1.0);\n"
351+ " v_texcoord = texcoord;\n"
352 "}\n"
353 };
354
355 std::string const fragment_shader
356 {
357 "precision mediump float;\n"
358+ "uniform sampler2D tex;\n"
359+ "varying vec2 v_texcoord;\n"
360 "void main() {\n"
361- " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
362+ " gl_FragColor = texture2D(tex, v_texcoord);\n"
363 "}\n"
364 };
365-}
366-mga::OverlayGLProgram::OverlayGLProgram(
367- GLProgramFactory const& factory, GLContext const& context)
368+
369+void set_display_transform(GLint uniform_loc, geom::Rectangle const& rect)
370+{
371+ glm::mat4 disp_transform(1.0);
372+
373+ disp_transform = glm::translate(disp_transform, glm::vec3{-1.0, 1.0, 0.0});
374+ disp_transform = glm::scale(
375+ disp_transform,
376+ glm::vec3{2.0/rect.size.width.as_float(),
377+ -2.0/rect.size.height.as_float(),
378+ 1.0});
379+ glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, glm::value_ptr(disp_transform));
380+}
381+}
382+
383+mga::HWCFallbackGLRenderer::HWCFallbackGLRenderer(
384+ GLProgramFactory const& factory,
385+ mg::GLContext const& context,
386+ geom::Rectangle const& screen_pos)
387 {
388 context.make_current();
389- overlay_program = factory.create_gl_program(vertex_shader, fragment_shader);
390+ program = factory.create_gl_program(vertex_shader, fragment_shader);
391+ texture_cache = factory.create_texture_cache();
392+
393+ glUseProgram(*program);
394+
395+ auto display_transform_uniform = glGetUniformLocation(*program, "display_transform");
396+ set_display_transform(display_transform_uniform, screen_pos);
397+
398+ position_attr = glGetAttribLocation(*program, "position");
399+ texcoord_attr = glGetAttribLocation(*program, "texcoord");
400+
401+ auto tex_loc = glGetUniformLocation(*program, "tex");
402+ glUniform1i(tex_loc, 0);
403+
404+ glBindBuffer(GL_ARRAY_BUFFER, 0);
405+
406+ glUseProgram(0);
407 context.release_current();
408 }
409
410-void mga::OverlayGLProgram::render(RenderableList const&, SwappingGLContext const&) const
411+void mga::HWCFallbackGLRenderer::render(
412+ RenderableList const& renderlist, SwappingGLContext const& context) const
413 {
414+ glUseProgram(*program);
415+
416+ glClearColor(0.0, 0.0, 0.0, 1.0);
417+ glClear(GL_COLOR_BUFFER_BIT);
418+
419+ glEnableVertexAttribArray(position_attr);
420+ glEnableVertexAttribArray(texcoord_attr);
421+
422+ for(auto const& renderable : renderlist)
423+ {
424+ auto const primitive = mg::tessellate_renderable_into_rectangle(*renderable);
425+ glVertexAttribPointer(position_attr, 3, GL_FLOAT, GL_FALSE, sizeof(mg::GLVertex),
426+ &primitive.vertices[0].position);
427+ //TODO: (kdub) scaling or pi/2 rotation eventually. for now, all quads get same texcoords
428+ glVertexAttribPointer(texcoord_attr, 2, GL_FLOAT, GL_FALSE, sizeof(mg::GLVertex),
429+ &primitive.vertices[0].texcoord);
430+
431+ texture_cache->load(*renderable)->bind();
432+ glDrawArrays(primitive.type, 0, primitive.vertices.size());
433+ }
434+
435+ glDisableVertexAttribArray(texcoord_attr);
436+ glDisableVertexAttribArray(position_attr);
437+ context.swap_buffers();
438+ texture_cache->drop_unused();
439+ glUseProgram(0);
440 }
441
442=== renamed file 'src/platform/graphics/android/overlay_gl_compositor.h' => 'src/platform/graphics/android/hwc_fallback_gl_renderer.h'
443--- src/platform/graphics/android/overlay_gl_compositor.h 2014-05-19 02:55:29 +0000
444+++ src/platform/graphics/android/hwc_fallback_gl_renderer.h 2014-05-22 16:51:59 +0000
445@@ -16,11 +16,12 @@
446 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
447 */
448
449-#ifndef MIR_GRAPHICS_ANDROID_OVERLAY_GL_PROGRAM_H_
450-#define MIR_GRAPHICS_ANDROID_OVERLAY_GL_PROGRAM_H_
451-
452+#ifndef MIR_GRAPHICS_ANDROID_HWC_FALLBACK_GL_RENDERER_H_
453+#define MIR_GRAPHICS_ANDROID_HWC_FALLBACK_GL_RENDERER_H_
454+#include "mir/geometry/rectangle.h"
455 #include "mir/graphics/gl_program.h"
456 #include "mir/graphics/renderable.h"
457+#include "mir/graphics/gl_texture_cache.h"
458 #include <memory>
459
460 namespace mir
461@@ -46,18 +47,25 @@
462 RenderableListCompositor& operator=(RenderableListCompositor const&) = delete;
463 };
464
465-class OverlayGLProgram : public RenderableListCompositor
466+class HWCFallbackGLRenderer : public RenderableListCompositor
467 {
468 public:
469- OverlayGLProgram(GLProgramFactory const& program_factory, graphics::GLContext const& gl_context);
470+ HWCFallbackGLRenderer(
471+ GLProgramFactory const& program_factory,
472+ graphics::GLContext const& gl_context,
473+ geometry::Rectangle const& screen_position);
474
475 void render(RenderableList const&, SwappingGLContext const&) const;
476 private:
477- std::unique_ptr<graphics::GLProgram> overlay_program;
478+ std::unique_ptr<graphics::GLProgram> program;
479+ std::unique_ptr<graphics::GLTextureCache> texture_cache;
480+
481+ GLint position_attr;
482+ GLint texcoord_attr;
483 };
484
485 }
486 }
487 }
488
489-#endif /* MIR_GRAPHICS_ANDROID_OVERLAY_GL_PROGRAM_H_ */
490+#endif /* MIR_GRAPHICS_ANDROID_HWC_FALLBACK_GL_RENDERER_H_ */
491
492=== modified file 'src/platform/graphics/android/hwc_fb_device.cpp'
493--- src/platform/graphics/android/hwc_fb_device.cpp 2014-05-19 02:55:29 +0000
494+++ src/platform/graphics/android/hwc_fb_device.cpp 2014-05-22 16:51:59 +0000
495@@ -22,7 +22,7 @@
496 #include "framebuffer_bundle.h"
497 #include "android_format_conversion-inl.h"
498 #include "hwc_wrapper.h"
499-#include "overlay_gl_compositor.h"
500+#include "hwc_fallback_gl_renderer.h"
501 #include "mir/graphics/buffer.h"
502 #include "mir/graphics/android/native_buffer.h"
503 #include "gl_context.h"
504
505=== modified file 'src/platform/graphics/gl_program.cpp'
506--- src/platform/graphics/gl_program.cpp 2014-05-22 11:31:21 +0000
507+++ src/platform/graphics/gl_program.cpp 2014-05-22 16:51:59 +0000
508@@ -76,7 +76,7 @@
509 return shader;
510 }
511
512-mg::GLProgram::GLProgram(
513+mg::SimpleGLProgram::SimpleGLProgram(
514 GLchar const* vertex_shader_src,
515 GLchar const* fragment_shader_src)
516 : vertex_shader(vertex_shader_src, GL_VERTEX_SHADER),
517@@ -98,12 +98,12 @@
518 }
519 }
520
521-mg::GLProgram::~GLProgram()
522+mg::SimpleGLProgram::~SimpleGLProgram()
523 {
524 glDeleteProgram(program);
525 }
526
527-mg::GLProgram::operator GLuint() const
528+mg::SimpleGLProgram::operator GLuint() const
529 {
530 return program;
531 }
532
533=== modified file 'src/server/compositor/gl_renderer.cpp'
534--- src/server/compositor/gl_renderer.cpp 2014-05-22 11:31:21 +0000
535+++ src/server/compositor/gl_renderer.cpp 2014-05-22 16:51:59 +0000
536@@ -149,7 +149,7 @@
537 tessellate(primitives, renderable);
538
539 auto surface_tex = texture_cache->load(renderable);
540-
541+
542 for (auto const& p : primitives)
543 {
544 // Note a primitive tex_id of zero means use the surface texture,
545
546=== modified file 'src/server/graphics/program_factory.cpp'
547--- src/server/graphics/program_factory.cpp 2014-04-16 19:00:03 +0000
548+++ src/server/graphics/program_factory.cpp 2014-05-22 16:51:59 +0000
549@@ -19,6 +19,7 @@
550
551 #include "program_factory.h"
552 #include "mir/graphics/gl_program.h"
553+#include "mir/compositor/recently_used_cache.h"
554
555 namespace mg = mir::graphics;
556
557@@ -28,5 +29,12 @@
558 std::string const& fragment_shader) const
559 {
560 std::lock_guard<decltype(mutex)> lock(mutex);
561- return std::unique_ptr<mg::GLProgram>(new GLProgram(vertex_shader.c_str(), fragment_shader.c_str()));
562+ return std::unique_ptr<mg::GLProgram>(
563+ new SimpleGLProgram(vertex_shader.c_str(), fragment_shader.c_str()));
564+}
565+
566+std::unique_ptr<mg::GLTextureCache> mg::ProgramFactory::create_texture_cache() const
567+{
568+ return std::unique_ptr<mg::GLTextureCache>(
569+ new mir::compositor::RecentlyUsedCache());
570 }
571
572=== modified file 'src/server/graphics/program_factory.h'
573--- src/server/graphics/program_factory.h 2014-04-16 19:00:03 +0000
574+++ src/server/graphics/program_factory.h 2014-05-22 16:51:59 +0000
575@@ -21,6 +21,7 @@
576
577 #include "mir/graphics/gl_program_factory.h"
578 #include "mir/graphics/gl_program.h"
579+#include "mir/graphics/gl_texture_cache.h"
580 #include <mutex>
581
582 namespace mir
583@@ -31,6 +32,7 @@
584 {
585 public:
586 std::unique_ptr<GLProgram> create_gl_program(std::string const&, std::string const&) const override;
587+ std::unique_ptr<GLTextureCache> create_texture_cache() const;
588
589 private:
590 /*
591
592=== modified file 'src/shared/geometry/rectangle.cpp'
593--- src/shared/geometry/rectangle.cpp 2013-10-15 08:53:10 +0000
594+++ src/shared/geometry/rectangle.cpp 2014-05-22 16:51:59 +0000
595@@ -28,6 +28,16 @@
596 top_left.y.as_int() + size.height.as_int()};
597 }
598
599+geom::Point geom::Rectangle::top_right() const
600+{
601+ return top_left + DeltaX{size.width.as_int()};
602+}
603+
604+geom::Point geom::Rectangle::bottom_left() const
605+{
606+ return top_left + DeltaY{size.height.as_int()};
607+}
608+
609 bool geom::Rectangle::contains(Rectangle const& r) const
610 {
611 return r.top_left.x >= top_left.x &&
612
613=== modified file 'tests/unit-tests/graphics/android/CMakeLists.txt'
614--- tests/unit-tests/graphics/android/CMakeLists.txt 2014-05-22 11:31:21 +0000
615+++ tests/unit-tests/graphics/android/CMakeLists.txt 2014-05-22 16:51:59 +0000
616@@ -27,7 +27,7 @@
617 ${CMAKE_CURRENT_SOURCE_DIR}/test_output_builder.cpp
618 ${CMAKE_CURRENT_SOURCE_DIR}/test_device_detection.cpp
619 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_wrapper.cpp
620- ${CMAKE_CURRENT_SOURCE_DIR}/test_overlay_compositor.cpp
621+ ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_fallback_gl_renderer.cpp
622 )
623
624 set(UNIT_TEST_SOURCES ${UNIT_TEST_SOURCES} PARENT_SCOPE)
625
626=== modified file 'tests/unit-tests/graphics/android/test_fb_device.cpp'
627--- tests/unit-tests/graphics/android/test_fb_device.cpp 2014-05-21 17:18:51 +0000
628+++ tests/unit-tests/graphics/android/test_fb_device.cpp 2014-05-22 16:51:59 +0000
629@@ -19,7 +19,7 @@
630 #include "mir_test_doubles/mock_fb_hal_device.h"
631 #include "mir_test_doubles/mock_buffer.h"
632 #include "src/platform/graphics/android/fb_device.h"
633-#include "src/platform/graphics/android/overlay_gl_compositor.h"
634+#include "src/platform/graphics/android/hwc_fallback_gl_renderer.h"
635 #include "mir_test_doubles/mock_framebuffer_bundle.h"
636 #include "mir_test_doubles/mock_android_hw.h"
637 #include "mir_test_doubles/mock_egl.h"
638
639=== modified file 'tests/unit-tests/graphics/android/test_hwc_display.cpp'
640--- tests/unit-tests/graphics/android/test_hwc_display.cpp 2014-05-22 11:31:21 +0000
641+++ tests/unit-tests/graphics/android/test_hwc_display.cpp 2014-05-22 16:51:59 +0000
642@@ -24,6 +24,7 @@
643 #include "mir_test_doubles/mock_display_report.h"
644 #include "mir_test_doubles/stub_renderable.h"
645 #include "mir_test_doubles/mock_egl.h"
646+#include "mir_test_doubles/mock_gl.h"
647 #include "mir/graphics/android/mir_native_window.h"
648 #include "mir_test_doubles/stub_driver_interpreter.h"
649 #include "mir_test_doubles/stub_display_buffer.h"
650@@ -103,6 +104,7 @@
651 }
652
653 testing::NiceMock<mtd::MockEGL> mock_egl;
654+ testing::NiceMock<mtd::MockGL> mock_gl;
655 mtd::StubGLProgramFactory stub_program_factory;
656
657 int visual_id;
658
659=== renamed file 'tests/unit-tests/graphics/android/test_overlay_compositor.cpp' => 'tests/unit-tests/graphics/android/test_hwc_fallback_gl_renderer.cpp'
660--- tests/unit-tests/graphics/android/test_overlay_compositor.cpp 2014-04-24 20:07:20 +0000
661+++ tests/unit-tests/graphics/android/test_hwc_fallback_gl_renderer.cpp 2014-05-22 16:51:59 +0000
662@@ -16,18 +16,30 @@
663 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
664 */
665
666-#include "src/platform/graphics/android/overlay_gl_compositor.h"
667+#include "src/platform/graphics/android/hwc_fallback_gl_renderer.h"
668 #include "mir/graphics/gl_context.h"
669 #include "mir/graphics/gl_program_factory.h"
670+#include "mir/graphics/gl_primitive.h"
671+#include "mir/graphics/gl_texture.h"
672 #include "mir_test_doubles/mock_gl.h"
673+#include "mir_test_doubles/mock_egl.h"
674+#include "mir_test_doubles/stub_renderable.h"
675+#include "mir_test_doubles/mock_swapping_gl_context.h"
676+#include "mir_test_doubles/stub_gl_program.h"
677 #include <gtest/gtest.h>
678 #include <mir_test/gmock_fixes.h>
679
680+#define GLM_FORCE_RADIANS
681+#define GLM_PRECISION_MEDIUMP_FLOAT
682+#include <glm/glm.hpp>
683+#include <glm/gtc/matrix_transform.hpp>
684+#include <glm/gtc/type_ptr.hpp>
685+
686 namespace mg=mir::graphics;
687 namespace mga=mir::graphics::android;
688 namespace mt=mir::test;
689 namespace mtd=mir::test::doubles;
690-
691+namespace geom=mir::geometry;
692 namespace
693 {
694
695@@ -36,6 +48,7 @@
696 public:
697 MOCK_CONST_METHOD2(create_gl_program,
698 std::unique_ptr<mg::GLProgram>(std::string const&, std::string const&));
699+ MOCK_CONST_METHOD0(create_texture_cache, std::unique_ptr<mg::GLTextureCache>());
700 };
701
702 class MockContext : public mg::GLContext
703@@ -45,23 +58,258 @@
704 MOCK_CONST_METHOD0(release_current, void());
705 };
706
707-class OverlayCompositor : public ::testing::Test
708+struct MockTextureCache : public mg::GLTextureCache
709+{
710+ MockTextureCache()
711+ {
712+ ON_CALL(*this, load(testing::_))
713+ .WillByDefault(testing::Return(std::make_shared<mg::GLTexture>()));
714+ }
715+ MOCK_METHOD1(load, std::shared_ptr<mg::GLTexture>(mg::Renderable const&));
716+ MOCK_METHOD0(invalidate, void());
717+ MOCK_METHOD0(drop_unused, void());
718+};
719+
720+class StubTextureCache : public mg::GLTextureCache
721+{
722+ std::shared_ptr<mg::GLTexture> load(mg::Renderable const&)
723+ {
724+ return std::make_shared<mg::GLTexture>();
725+ }
726+ void invalidate()
727+ {
728+ }
729+ void drop_unused()
730+ {
731+ }
732+};
733+
734+class HWCFallbackGLRenderer : public ::testing::Test
735 {
736 public:
737+ HWCFallbackGLRenderer()
738+ {
739+ using namespace testing;
740+ ON_CALL(mock_gl_program_factory,create_gl_program(_,_))
741+ .WillByDefault(Invoke([](std::string const, std::string const)
742+ { return std::unique_ptr<mg::GLProgram>(new mtd::StubGLProgram); }));
743+ ON_CALL(mock_gl_program_factory,create_texture_cache())
744+ .WillByDefault(Invoke([]()
745+ { return std::unique_ptr<mg::GLTextureCache>(new StubTextureCache); }));
746+
747+ ON_CALL(mock_gl, glGetShaderiv(_,_,_))
748+ .WillByDefault(SetArgPointee<2>(GL_TRUE));
749+ ON_CALL(mock_gl, glGetProgramiv(_,_,_))
750+ .WillByDefault(SetArgPointee<2>(GL_TRUE));
751+ ON_CALL(mock_gl, glGetUniformLocation(_, StrEq("display_transform")))
752+ .WillByDefault(Return(display_transform_uniform_loc));
753+ ON_CALL(mock_gl, glGetUniformLocation(_, StrEq("tex")))
754+ .WillByDefault(Return(tex_uniform_loc));
755+ ON_CALL(mock_gl, glGetAttribLocation(_, StrEq("position")))
756+ .WillByDefault(Return(position_attr_loc));
757+ ON_CALL(mock_gl, glGetAttribLocation(_, StrEq("texcoord")))
758+ .WillByDefault(Return(texcoord_attr_loc));
759+ ON_CALL(mock_gl, glGenTextures(1,_))
760+ .WillByDefault(SetArgPointee<1>(texid));
761+ }
762+
763+ GLint const display_transform_uniform_loc{1};
764+ GLint const position_attr_loc{2};
765+ GLint const texcoord_attr_loc{3};
766+ GLint const tex_uniform_loc{4};
767+ GLint const texid{5};
768+ size_t const stride{sizeof(mg::GLVertex)};
769+
770 testing::NiceMock<MockGLProgramFactory> mock_gl_program_factory;
771 testing::NiceMock<MockContext> mock_context;
772 testing::NiceMock<mtd::MockGL> mock_gl;
773+ testing::NiceMock<mtd::MockEGL> mock_egl;
774+ geom::Rectangle dummy_screen_pos{geom::Point{0,0}, geom::Size{500,400}};
775 };
776-
777 }
778
779-TEST_F(OverlayCompositor, compiles_in_constructor)
780+TEST_F(HWCFallbackGLRenderer, compiles_and_sets_up_gl_program)
781 {
782 using namespace testing;
783 InSequence seq;
784 EXPECT_CALL(mock_context, make_current());
785 EXPECT_CALL(mock_gl_program_factory, create_gl_program(_,_));
786+ EXPECT_CALL(mock_gl, glUseProgram(_));
787+ EXPECT_CALL(mock_gl, glGetUniformLocation(_, StrEq("display_transform")));
788+ EXPECT_CALL(mock_gl, glGetAttribLocation(_, StrEq("position")));
789+ EXPECT_CALL(mock_gl, glGetAttribLocation(_, StrEq("texcoord")));
790+ EXPECT_CALL(mock_gl, glGetUniformLocation(_, StrEq("tex")));
791+ EXPECT_CALL(mock_gl, glUniform1i(tex_uniform_loc, 0));
792+ EXPECT_CALL(mock_gl, glUseProgram(0));
793 EXPECT_CALL(mock_context, release_current());
794
795- mga::OverlayGLProgram glprogram(mock_gl_program_factory, mock_context);
796+ mga::HWCFallbackGLRenderer glprogram(mock_gl_program_factory, mock_context, dummy_screen_pos);
797+}
798+
799+MATCHER_P(Matches4x4Matrix, value, "matches expected 4x4 matrix")
800+{
801+ for(auto i=0; i < 16; i++)
802+ EXPECT_THAT(arg[i], testing::FloatEq(value[i]));
803+ return !(::testing::Test::HasFailure());
804+}
805+
806+TEST_F(HWCFallbackGLRenderer, sets_up_orthographic_matrix_based_on_screen_size)
807+{
808+ using namespace testing;
809+ geom::Size sz{800,600};
810+ geom::Point pt{100,200};
811+ geom::Rectangle screen_pos{pt, sz};
812+ float inv_w = 2.0/sz.width.as_int();
813+ float inv_h = 2.0/sz.height.as_int() * -1.0;
814+
815+ float expected_matrix[]{
816+ inv_w, 0.0 , 0.0, 0.0,
817+ 0.0 , inv_h , 0.0, 0.0,
818+ 0.0 , 0.0 , 1.0, 0.0,
819+ -1.0 , 1.0 , 0.0, 1.0
820+ };
821+
822+ EXPECT_CALL(mock_gl, glUniformMatrix4fv(
823+ display_transform_uniform_loc, 1, GL_FALSE, Matches4x4Matrix(expected_matrix)));
824+
825+ mga::HWCFallbackGLRenderer glprogram(mock_gl_program_factory, mock_context, screen_pos);
826+}
827+
828+struct Vertex
829+{
830+ float x;
831+ float y;
832+};
833+
834+Vertex to_vertex(geom::Point const& pos)
835+{
836+ return {
837+ static_cast<float>(pos.x.as_int()),
838+ static_cast<float>(pos.y.as_int())
839+ };
840+}
841+
842+MATCHER_P2(MatchesVertices, vertices, stride, "matches vertices")
843+{
844+ auto arg_vertices = static_cast<char const*>(arg);
845+ for(auto const& vert : vertices)
846+ {
847+ GLfloat *f = (GLfloat*) arg_vertices;
848+ EXPECT_THAT(f[0], testing::FloatEq(vert.x));
849+ EXPECT_THAT(f[1], testing::FloatEq(vert.y));
850+ arg_vertices+=stride;
851+ }
852+ return !(::testing::Test::HasFailure());
853+}
854+
855+TEST_F(HWCFallbackGLRenderer, computes_vertex_coordinates_correctly)
856+{
857+ using namespace testing;
858+ NiceMock<mtd::MockSwappingGLContext> mock_context_s;
859+ geom::Rectangle rect1{{100,200},{50, 60}};
860+ geom::Rectangle rect2{{150,250},{150, 90}};
861+
862+ mg::RenderableList renderlist{
863+ std::make_shared<mtd::StubRenderable>(rect1),
864+ std::make_shared<mtd::StubRenderable>(rect2)
865+ };
866+
867+ std::vector<Vertex> expected_vertices1 {
868+ to_vertex(rect1.top_left),
869+ to_vertex(rect1.bottom_left()),
870+ to_vertex(rect1.top_right()),
871+ to_vertex(rect1.bottom_right()),
872+ };
873+ std::vector<Vertex> expected_vertices2 {
874+ to_vertex(rect2.top_left),
875+ to_vertex(rect2.bottom_left()),
876+ to_vertex(rect2.top_right()),
877+ to_vertex(rect2.bottom_right()),
878+ };
879+
880+ InSequence seq;
881+ EXPECT_CALL(mock_gl, glVertexAttribPointer(
882+ position_attr_loc, 3, GL_FLOAT, GL_FALSE, stride, MatchesVertices(expected_vertices1, stride)));
883+ EXPECT_CALL(mock_gl, glVertexAttribPointer(_,_,_,_,_,_))
884+ .Times(1);
885+ EXPECT_CALL(mock_gl, glVertexAttribPointer(
886+ position_attr_loc, 3, GL_FLOAT, GL_FALSE, stride, MatchesVertices(expected_vertices2, stride)));
887+ EXPECT_CALL(mock_gl, glVertexAttribPointer(_,_,_,_,_,_))
888+ .Times(1);
889+
890+ mga::HWCFallbackGLRenderer glprogram(mock_gl_program_factory, mock_context, dummy_screen_pos);
891+ glprogram.render(renderlist, mock_context_s);
892+}
893+
894+TEST_F(HWCFallbackGLRenderer, computes_texture_coordinates_correctly)
895+{
896+ using namespace testing;
897+ NiceMock<mtd::MockSwappingGLContext> mock_context_s;
898+ geom::Rectangle rect1{{100,200},{50, 60}};
899+ geom::Rectangle rect2{{150,250},{150, 90}};
900+
901+ mg::RenderableList renderlist{
902+ std::make_shared<mtd::StubRenderable>(rect1),
903+ std::make_shared<mtd::StubRenderable>(rect2)
904+ };
905+
906+ std::vector<Vertex> expected_texcoord {
907+ {0.0f, 0.0f},
908+ {0.0f, 1.0f},
909+ {1.0f, 0.0f},
910+ {1.0f, 1.0f}
911+ };
912+
913+ EXPECT_CALL(mock_gl, glVertexAttribPointer(_,_,_,_,_,_)).Times(AnyNumber());
914+ EXPECT_CALL(mock_gl, glVertexAttribPointer(
915+ texcoord_attr_loc, 2, GL_FLOAT, GL_FALSE, stride, MatchesVertices(expected_texcoord, stride)))
916+ .Times(2);
917+
918+ mga::HWCFallbackGLRenderer glprogram(mock_gl_program_factory, mock_context, dummy_screen_pos);
919+ glprogram.render(renderlist, mock_context_s);
920+}
921+
922+TEST_F(HWCFallbackGLRenderer, executes_render_in_sequence)
923+{
924+ using namespace testing;
925+ NiceMock<mtd::MockSwappingGLContext> mock_context_s;
926+ auto renderable1 = std::make_shared<mtd::StubRenderable>();
927+ auto renderable2 = std::make_shared<mtd::StubRenderable>();
928+ mg::RenderableList renderlist{ renderable1, renderable2 };
929+
930+ std::unique_ptr<MockTextureCache> mock_texture_cache(new MockTextureCache);
931+ {
932+ InSequence seq;
933+ EXPECT_CALL(*mock_texture_cache, load(Ref(*renderable1)));
934+ EXPECT_CALL(*mock_texture_cache, load(Ref(*renderable2)));
935+ EXPECT_CALL(*mock_texture_cache, drop_unused());
936+ }
937+ ON_CALL(mock_gl_program_factory,create_texture_cache())
938+ .WillByDefault(Invoke([&](){
939+ return std::move(mock_texture_cache);
940+ }));
941+
942+ mga::HWCFallbackGLRenderer glprogram(mock_gl_program_factory, mock_context, dummy_screen_pos);
943+
944+ InSequence seq;
945+ EXPECT_CALL(mock_gl, glUseProgram(_));
946+ EXPECT_CALL(mock_gl, glClearColor(FloatEq(0.0), FloatEq(0.0), FloatEq(0.0), FloatEq(1.0)));
947+ EXPECT_CALL(mock_gl, glClear(GL_COLOR_BUFFER_BIT));
948+ EXPECT_CALL(mock_gl, glEnableVertexAttribArray(position_attr_loc));
949+ EXPECT_CALL(mock_gl, glEnableVertexAttribArray(texcoord_attr_loc));
950+
951+ EXPECT_CALL(mock_gl, glVertexAttribPointer(position_attr_loc, 3, GL_FLOAT, GL_FALSE, _, _));
952+ EXPECT_CALL(mock_gl, glVertexAttribPointer(texcoord_attr_loc, 2, GL_FLOAT, GL_FALSE, _, _));
953+ EXPECT_CALL(mock_gl, glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
954+
955+ EXPECT_CALL(mock_gl, glVertexAttribPointer(position_attr_loc, 3, GL_FLOAT, GL_FALSE, _, _));
956+ EXPECT_CALL(mock_gl, glVertexAttribPointer(texcoord_attr_loc, 2, GL_FLOAT, GL_FALSE, _, _));
957+ EXPECT_CALL(mock_gl, glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
958+
959+ EXPECT_CALL(mock_gl, glDisableVertexAttribArray(texcoord_attr_loc));
960+ EXPECT_CALL(mock_gl, glDisableVertexAttribArray(position_attr_loc));
961+ EXPECT_CALL(mock_context_s, swap_buffers());
962+ EXPECT_CALL(mock_gl, glUseProgram(0));
963+
964+ glprogram.render(renderlist, mock_context_s);
965 }
966
967=== modified file 'tests/unit-tests/graphics/android/test_hwc_fb_device.cpp'
968--- tests/unit-tests/graphics/android/test_hwc_fb_device.cpp 2014-05-21 17:18:51 +0000
969+++ tests/unit-tests/graphics/android/test_hwc_fb_device.cpp 2014-05-22 16:51:59 +0000
970@@ -30,7 +30,7 @@
971 #include "mir_test_doubles/mock_hwc_device_wrapper.h"
972 #include "mir_test_doubles/stub_renderable_list_compositor.h"
973 #include "mir_test_doubles/mock_renderable_list_compositor.h"
974-#include "src/platform/graphics/android/overlay_gl_compositor.h"
975+#include "src/platform/graphics/android/hwc_fallback_gl_renderer.h"
976 #include "hwc_struct_helpers.h"
977 #include <gtest/gtest.h>
978 #include <stdexcept>
979
980=== modified file 'tests/unit-tests/graphics/android/test_output_builder.cpp'
981--- tests/unit-tests/graphics/android/test_output_builder.cpp 2014-05-07 02:56:33 +0000
982+++ tests/unit-tests/graphics/android/test_output_builder.cpp 2014-05-22 16:51:59 +0000
983@@ -28,6 +28,7 @@
984 #include "mir_test_doubles/mock_android_hw.h"
985 #include "mir_test_doubles/mock_fb_hal_device.h"
986 #include "mir_test_doubles/mock_egl.h"
987+#include "mir_test_doubles/mock_gl.h"
988 #include "mir_test_doubles/mock_android_native_buffer.h"
989 #include "mir_test_doubles/stub_gl_config.h"
990 #include "mir_test_doubles/stub_gl_program_factory.h"
991@@ -98,6 +99,7 @@
992 }
993
994 testing::NiceMock<mtd::MockEGL> mock_egl;
995+ testing::NiceMock<mtd::MockGL> mock_gl;
996 testing::NiceMock<mtd::HardwareAccessMock> hw_access_mock;
997 testing::NiceMock<mtd::MockFBHalDevice> fb_hal_mock;
998 std::shared_ptr<MockResourceFactory> mock_resource_factory;

Subscribers

People subscribed via source and target branches