blob: f0e176783a87f7b98c011548ad6a60930ed60880 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "color_source.h"
#include <lib/syslog/cpp/macros.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>
#include <array>
namespace camera {
// To fill an ARGB32 image, you have the following offsets:
static constexpr uint8_t kAlphaShift = 24;
static constexpr uint8_t kRedShift = 16;
static constexpr uint8_t kGreenShift = 8;
// Set the alpha value to 100%:
static constexpr uint8_t kAlphaValue = 0xff;
static constexpr uint32_t kLowByteMask = 0xff;
static constexpr uint32_t kLowThreeBitMask = 0x7;
static constexpr uint32_t kUint8Max = 0xff;
// Every new frame, we increment by kFrameColorInc. There are kNumberOfPhases, and each phase
// takes 2^kIndexDownshift steps.
static constexpr uint32_t kFrameColorInc = 0x01;
static constexpr uint8_t kIndexDownshift = 8;
static constexpr uint8_t kNumberOfPhases = 6;
// The cycle repeats after kNumberOfPhases * 2^kIndexDownshift steps.
static constexpr uint32_t kMaxFrameColor = kNumberOfPhases << kIndexDownshift;
// To cover the HSV color space, R,G,B go through the phases offset by the following:
static constexpr uint8_t kRedPhaseOffset = 1;
static constexpr uint8_t kGreenPhaseOffset = 5;
static constexpr uint8_t kBluePhaseOffset = 3;
void ColorSource::FillARGB(void* start, size_t buffer_size) {
if (!start) {
FX_LOGS(ERROR) << "Must pass a valid buffer pointer";
return;
}
uint8_t r, g, b;
hsv_color(frame_color_, &r, &g, &b);
FX_LOGS(DEBUG) << "Filling with " << static_cast<int>(r) << " " << static_cast<int>(g) << " "
<< static_cast<int>(b);
uint32_t color = kAlphaValue << kAlphaShift | r << kRedShift | g << kGreenShift | b;
ZX_DEBUG_ASSERT(buffer_size % 4 == 0);
size_t num_pixels = buffer_size / 4;
auto* pixels = reinterpret_cast<uint32_t*>(start);
for (uint32_t i = 0; i < num_pixels; i++) {
pixels[i] = color;
}
// Ignore if flushing the cache fails.
zx_cache_flush(start, buffer_size, ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE);
frame_color_ += kFrameColorInc;
if (frame_color_ > kMaxFrameColor) {
frame_color_ -= kMaxFrameColor;
}
}
void ColorSource::hsv_color(uint32_t index, uint8_t* r, uint8_t* g, uint8_t* b) {
index = index % kMaxFrameColor;
uint8_t pos = index & kLowByteMask;
uint8_t neg = kLowByteMask - (index & kLowByteMask);
uint8_t phase = (index >> kIndexDownshift) & kLowThreeBitMask;
std::array<uint8_t, kNumberOfPhases> phases = {kUint8Max, kUint8Max, neg, 0x00, 0x00, pos};
*r = phases[(phase + kRedPhaseOffset) % phases.size()];
*g = phases[(phase + kGreenPhaseOffset) % phases.size()];
*b = phases[(phase + kBluePhaseOffset) % phases.size()];
}
} // namespace camera