[waffle] [PATCH v3] nacl: add implementation for waffle_window_swap_buffers

Tapani Pälli tapani.palli at intel.com
Thu Feb 12 00:06:09 PST 2015



On 02/12/2015 03:47 AM, Chad Versace wrote:
> On 02/09/2015 06:22 AM, Tapani Pälli wrote:
>> Implementation for nacl is somewhat different as for other platforms,
>> platform needs to ensure that the previous swap has finished before
>> issuing GL commands or more swaps. This is done by introducing a worker
>> thread that does buffer swaps from a work queue and uses a semaphore to
>> lock main thread until swap is finished.
>>
>> v2: add error messaging if pp::Graphics3D::SwapBuffers fails
>>      add semaphore to implement blocking swap()
>>      remove extra nacl_swapbuffers() c++ function (Chad, Emil)
>>
>> v3: destroy semaphore when thread dies
>>
>> Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
>> ---
>>   src/waffle/nacl/nacl_container.cpp | 12 +++++
>>   src/waffle/nacl/nacl_container.h   |  2 +-
>>   src/waffle/nacl/nacl_swap_thread.h | 94 ++++++++++++++++++++++++++++++++++++++
>>   src/waffle/nacl/nacl_window.c      |  3 +-
>>   4 files changed, 109 insertions(+), 2 deletions(-)
>>   create mode 100644 src/waffle/nacl/nacl_swap_thread.h
>>
>> diff --git a/src/waffle/nacl/nacl_container.cpp b/src/waffle/nacl/nacl_container.cpp
>> index fe907ff..84ab1da 100644
>> --- a/src/waffle/nacl/nacl_container.cpp
>> +++ b/src/waffle/nacl/nacl_container.cpp
>> @@ -28,11 +28,13 @@
>>   #include "ppapi/cpp/module.h"
>>   #include "ppapi/c/pp_errors.h"
>>   #include "nacl_container.h"
>> +#include "nacl_swap_thread.h"
>>
>>   namespace waffle {
>>
>>   struct nacl_container {
>>       pp::Graphics3D *ctx;
>> +    NaclSwapThread *swapper;
>>
>>       void *glapi;
>>       bool (*glInitializePPAPI) (PPB_GetInterface);
>> @@ -49,6 +51,7 @@ nacl_container_dtor(waffle::nacl_container *nc)
>>       if (nc->glapi)
>>           dlclose(nc->glapi);
>>
>> +    delete nc->swapper;
>>       delete nc;
>>   }
>>
>> @@ -119,6 +122,7 @@ nacl_context_init(waffle::nacl_container *nc, struct nacl_config *cfg)
>>           return false;
>>       }
>>
>> +    nc->swapper = new NaclSwapThread(pp_instance, nc->ctx);
>>       return true;
>>   }
>>
>> @@ -194,3 +198,11 @@ nacl_makecurrent(nacl_container *nc, bool release)
>>
>>       return true;
>>   }
>> +
>> +extern "C" bool
>> +nacl_swapbuffers(nacl_container *nc)
>> +{
>> +    waffle::nacl_container *cpp_nc =
>> +        reinterpret_cast<waffle::nacl_container*>(nc);
>> +    return cpp_nc->swapper->swap();
>> +}
>> diff --git a/src/waffle/nacl/nacl_container.h b/src/waffle/nacl/nacl_container.h
>> index ca26a1f..579856d 100644
>> --- a/src/waffle/nacl/nacl_container.h
>> +++ b/src/waffle/nacl/nacl_container.h
>> @@ -43,7 +43,7 @@ bool nacl_context_init(struct nacl_container *nc, struct nacl_config *cfg);
>>   bool nacl_resize(struct nacl_container *nc, int32_t width, int32_t height);
>>   bool nacl_makecurrent(struct nacl_container *nc, bool release);
>>   void nacl_context_fini(struct nacl_container *nc);
>> -
>> +bool nacl_swapbuffers(struct nacl_container *nc);
>>   #ifdef __cplusplus
>>   };
>>   #endif
>> diff --git a/src/waffle/nacl/nacl_swap_thread.h b/src/waffle/nacl/nacl_swap_thread.h
>> new file mode 100644
>> index 0000000..8e8687b
>> --- /dev/null
>> +++ b/src/waffle/nacl/nacl_swap_thread.h
>> @@ -0,0 +1,94 @@
>> +// Copyright 2014 Intel Corporation
>> +//
>> +// All rights reserved.
>> +//
>> +// Redistribution and use in source and binary forms, with or without
>> +// modification, are permitted provided that the following conditions are met:
>> +//
>> +// - Redistributions of source code must retain the above copyright notice, this
>> +//   list of conditions and the following disclaimer.
>> +//
>> +// - Redistributions in binary form must reproduce the above copyright notice,
>> +//   this list of conditions and the following disclaimer in the documentation
>> +//   and/or other materials provided with the distribution.
>> +//
>> +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
>> +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>> +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>> +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
>> +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
>> +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
>> +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>> +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
>> +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>> +
>> +#include "ppapi/cpp/graphics_3d.h"
>> +#include "ppapi/cpp/instance.h"
>> +#include "ppapi/utility/completion_callback_factory.h"
>> +#include "ppapi/utility/threading/simple_thread.h"
>> +#include "wcore_error.h"
>> +#include <semaphore.h>
>> +
>> +// Thread takes care that we do not issue another buffer
>> +// swap before previous swap has completed.
>> +class NaclSwapThread : public pp::SimpleThread
>> +{
>> +public:
>> +    explicit NaclSwapThread(const pp::InstanceHandle &instance,
>> +                            pp::Graphics3D *_ctx) :
>> +        pp::SimpleThread(instance),
>> +        ctx(_ctx),
>> +        cbf(this)
>> +    {
>> +        Start();
>> +        sem_init(&sem, 0, 0);
>> +    }
>> +
>> +    ~NaclSwapThread()
>> +    {
>> +        sem_destroy(&sem);
>> +        message_loop().PostQuit(true);
>> +    }
>> +
>> +    bool swap()
>> +    {
>> +        pp::CompletionCallback cb =
>> +            cbf.NewCallback(&NaclSwapThread::swap_buffers);
>> +
>> +        if (message_loop().PostWork(cb) != PP_OK)
>> +            return false;
>
> I don't understand NaCl's message loop. When you post a callback
> to the message loop, does NaCl provide any guarantees on which
> thread executes the callback?

message_loop() is method of SimpleThread so here it returns the 
message_loop of NaclSwapThread, I used the method because examples I've 
seen did this. I could've done also 'message_loop_.PostWork(cb)'. I can 
change this if it feels/looks bad (?)

>> +
>> +        sem_wait(&sem);
>> +
>> +        return true;
>> +    }
>> +
>> +private:
>> +
>> +    void swap_buffers(int32_t result)
>> +    {
>> +        int32_t error = ctx->SwapBuffers(pp::BlockUntilComplete());
>> +        switch (error) {
>> +            case PP_OK:
>> +                break;
>> +            case PP_ERROR_NOMEMORY:
>> +                wcore_errorf(WAFFLE_ERROR_BAD_ALLOC,
>> +                             "pp::Graphics3D::SwapBuffers: Out of memory.");
>> +                break;
>> +            case PP_ERROR_CONTEXT_LOST:
>> +                wcore_errorf(WAFFLE_ERROR_FATAL,
>> +                             "pp::Graphics3D::SwapBuffers: 3D context lost.");
>> +                break;
>> +            default:
>> +                wcore_errorf(WAFFLE_ERROR_UNKNOWN,
>> +                             "pp::Graphics3D::SwapBuffers: Unknown error.");
>> +                break;
>> +        }
>> +        sem_post(&sem);
>> +    }
>> +
>> +    pp::Graphics3D *ctx;
>> +    pp::CompletionCallbackFactory<NaclSwapThread> cbf;
>> +    sem_t sem;
>> +};
>> diff --git a/src/waffle/nacl/nacl_window.c b/src/waffle/nacl/nacl_window.c
>> index 7b7121f..5ac031c 100644
>> --- a/src/waffle/nacl/nacl_window.c
>> +++ b/src/waffle/nacl/nacl_window.c
>> @@ -97,5 +97,6 @@ nacl_window_resize(struct wcore_window *wc_self,
>>   bool
>>   nacl_window_swap_buffers(struct wcore_window *wc_self)
>>   {
>> -    return false;
>> +    struct nacl_platform *plat = nacl_platform(wc_self->display->platform);
>> +    return nacl_swapbuffers(plat->nacl);
>>   }
>>
>
>


More information about the waffle mailing list